Adding and Retrieving Players in a simple Pre-Flop Poker Hud with Local Storage
To Your Questions


Is there a benefit to using Classes? Right now I don't see the benefit of having a handle, like, player1 = new Player(arg,arg,etc...), player2 = new Player(arg,arg, etc...)...


Maybe there are benefits, but I can't think of any serious ones now.
The current version is similar to the factory pattern, where the creation of an object is abstracted by a factory - in this case addPlayer:
const player = addPlayer('Harry Potter');




Is there a better way to store to Local Storage? I don't think storing each player with their own key and having a ton of entries is a good idea.


I think storing all players under one key is sufficient and the easiest to manage. But you can get the best of both worlds:
Currently you are saving an array of players. Instead you could save a map where the key is a unique attribute of the player (maybe the name or an id) and the player itself. The benefit would be that you do not need to loop through an array to find a player:
function getPlayersFromStorage(key) {
  /* ... read from storage ... */;
  /* return has the form:
     {
        playername: player
     }
  */
}

const players = getPlayersFromStorage(localStorageKey);
const harryPotter = players[&quot;Harry Potter&quot;];

This is only necessary if you need to find players directly.



In my function addPlayer() should I be calling savePlayersToStorage in my localStorageUtils.js?


It depends. Currently the method name addPlayer does not represent what the method does. When I first read the name I thought: &quot;Ah ok, this methods put a player in some collection or maybe the local storage&quot;. But then I read the following line and get confused:

players.push(addPlayer(newPlayer));


A better name for addPlayer would be createPlayer and I would not call savePlayersToStorage in it, to have smaller and side effect free functions.
Change Persistenz

I am currently using local storage to store my data. In the future I will use a better persistence strategy

Currently, only the main.js depends on localStorage, and knows the implementation details, which would make it easier to change it in the future. However, to make it easier to change, especially as the code grows and more files depend on the persistence implementation, it should be abstracted as much as possible:
class LocalStorage {
    getAll() { /* ... */ }
    getByName() { /* ... */ }
    save()  { /* ... */ }
}

class OtherStorage {
    getAll() { /* ... */ }
    getByName() { /* ... */ }
    save()  { /* ... */ }
}

When your different storage strategies share the same interface they are easy interchange able:
// Main.js

const storage = new LocalStorage('my-storage-key');
# const storage = new OtherStorage(/* dependencies */);

function main() {
    const players = storage.getAllPlayers();
    const harryPotter = storage.getPlayerByName('Harry Potter');

    const newPlayer = createPlayer('Ron Weasley');
    const storage.save(newPlayer);
}

Read from Store

function getPlayersFromStorage(localStorageKey) {
 if (localStorage.getItem(localStorageKey === null)) {
   localStorage.setItem(localStorageKey);
 }
 let players = JSON.parse(localStorage.getItem(localStorageKey));

 return players;
}


When reading from the store we set an item if the key does not exists with localStorage.setItem(localStorageKey). To set an item is not the responsibility for reading data. Instead we could add some logic which is related for reading. For example if there is stored data under the given key:
function getPlayersFromStorage(localStorageKey) {
    const fromStore = localStorage.getItem(localStorageKey);
   
    if (fromSore) {
        return [];
    }
    
    return JSON.parse(fromStore);
}