That Javascript has (extended) class!

kevhines

kevhines

Posted on May 7, 2021

That Javascript has (extended) class!

Let's talk extending classes in JavaScript.

I wrote a single page JavaScript game that I called Gibberish Cards. It's kinda like War... but dumber.

It didn't use a typical card deck, and the names of the cards were user defined. This mean I needed a list of what cards were in the game and a subset of those cards that had names. In addition I needed to know which cards a user had in his draw pile and which cards a computer had in his draw pile. I also needed to know which cards the user and computer had in their discard pile. That's 6 arrays of card objects!

So I created a Deck class.

A Simple Class

class Deck {

    constructor() {
        this.unplayedCards = []
    }

    addCardtoDeck(card) {
        this.unplayedCards.push(card)
    }


    findCard(id) {
        return this.unplayedCards.find(card => card.id === id)
    }

}
Enter fullscreen mode Exit fullscreen mode

I called the array of cards unplayedCards because I needed to know which cards had not already been used in the game. I had two functions in this class addCardtoDeck which was great when the game first started as I filled in all those different decks I talked about. And occasionally I need to find a card object so the findCard function was very useful.

But I also needed to keep track of what named cards existed. The computer only ever had named cards, and I didn't need to keep the named and unnamed cards separate for the user so I only needed a list of all the named cards in the game before starting.

Rather then keep track of those named cards in all Deck classes I extended the Deck class to an AllCards class.

Extending and Using super

class AllCards extends Deck {

    constructor() {
        super()
        this.namedCards = []
    }

    addCardtoDeck(card) {
        super.addCardtoDeck(card)
        if (card.name) {
            this.namedCards.push(card)
        }
    }

    resetNamed() {
        this.namedCards = this.unplayedCards.filter(card => card.name)
    }

}
Enter fullscreen mode Exit fullscreen mode

Because this extends from Deck I had access to the findCard and addCardtoDeck function. My constructor needed both an unplayedCards array and a namedCards array. I used the code from the Deck class by calling the super() method in the constructor.

I determined which cards were named as I filled cards into those arrays via AddCardtoDeck so I also had to extend that function. You can see in the extended function I call super.addCardtoDeck(card) to add a card to my unplayedCards array but then I have new code where I add any named cards to the namedCard array.

This would be a pointless array in the user's deck and the computer's deck so I avoided the two extra array of card objects.

I also created a function just in the AllCards class called resetNamed() which is useful after a game ends. If a user wants to play again I don't want to re-upload all the card details from the database so it recreates the namedCards array with any cards that got named during the most recent game.

There was also a lot of functions I used in the two game decks that I never needed to use for the repository of all cards so I extended another class from Deck.

Another Extended Class

class PlayableDeck extends Deck {

    constructor() {
        super()
        this.playedCards = []
    }

// here is where I placed all the functions 
// only applicable to this class.

}

Enter fullscreen mode Exit fullscreen mode

Similar to the AllCards* class this extends from **Deck, uses super to create a this.unplayedCards array but then also creates an array for game decks that keeps track of which cards have been played since the last reshuffle. A discard pile, if you will. I called that playedCards.

Now that I had a PlayableDeck class I was able to create a slew of functions for game play that did not need to sit in the Deck class.

  • drawCard() - randomly draws an unplayed card
  • moveCardToPlayed(card) - moves a card (say that card I got from drawCard()) into the playedCards array.
  • removeCardFromDeck() - removes a card from played. This is used when your opponent takes your card.
  • totalCards() and totalUnplayedCards() to keep track of draw and discard piles. These are also critical to know when you need to reshuffle or when you've lost the game!
  • clear() - this function is clearing all cards after a game ends so you can start a new game cleanly.

3 Uniquely Similar Objects!

By extending the class I was able to have 3 Deck objects used in my code that didn't have functions or arrays baked in they would never use. It made the code cleaner and made testing easier while I coded the gameplay functionality.

Extend your classes! It's easy!

💖 💪 🙅 🚩
kevhines
kevhines

Posted on May 7, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related