0

I am writing a simple JavaScript application. The code consists of creating an object deck which can have many nested card objects.

Basically, I wanted to be able to access each card in a deck instance like this:

deck1.card2.method();

I have used the following function to create my deck prototype:

function Deck(){
var cardStack = []
//deck properties & methods
}

function card(){
//card properties methods
}

I've been adding each card to the deck and storing them in the cardStack array, using push and pop methods of JavaScript arrays.

This however does not allow me to access my cards as I wished to do:

deck1.card2.method();

Can anyone point me in the right way to achieve this? Is it possible in JavaScript? Thank you in advance :-)

Hirvesh
  • 7,636
  • 15
  • 59
  • 72

3 Answers3

2

You need to define the objects and functions as properties of the parent object by using this:

function Deck() {
  this.cardStack = [];
  this.card = function() {
    console.log('Hullo');
  }
}

Now calling the method works:

var deck = new Deck();
deck.card();   // Prints 'Hullo'
Blender
  • 289,723
  • 53
  • 439
  • 496
1

To access the single card objects, you will need to make your cardStack a public property. Inside the constructor, the this keyword is a reference to the current Deck object, so you can use:

function Deck(){
   this.cards = [];
   // deck properties & methods
}

Then, access a single card of var deck = new Deck(…) via deck.cards[2], and call a method of it.

Or you use an accessor function to the cardStack array. Extended example:

var Deck = (function() {
    function Deck() {
        var cardStack = [];
        this.getCard = function(i) { return cardStack[i]; };

        for (var i=0; i<5; i++)
            cardStack.push(new Card(i));
    }
    function Card(i) {
        this.method = function() {
            alert("Hi, I'm card №"+i);
        };
    }
    return Deck;
})();

var deck = new Deck();
deck.getCard(2).method(); // alerts "Hi, I'm card №2"
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Is it possible NOT to allow a user to create a card without creating a deck first? I mean, here, we can create just a card instance by new Card(i). How would it be possible to achieve that? Thanks for all your help! :-) – Hirvesh Aug 04 '12 at 17:26
  • You can use a [closure](http://stackoverflow.com/q/111102/1048572) to hide the `Card` constructor from the public. But why would you want to do that? – Bergi Aug 04 '12 at 17:30
  • that's because every card must always belong to a deck :p Without wanting to be asking too much, can you just edit your example to show me how to create the closure and create new instances of card within the deck? Please? – Hirvesh Aug 04 '12 at 17:32
  • It might be an easier approach to give the card constructor the deck to which the new card should be added as an argument. However, if your application adds all cards it creates to some decks, there is no need to hide it from the public. Technically speaking, there would always be a way to create card instances without a deck - just don't *do* it - but you can't *hinder* anyone. – Bergi Aug 04 '12 at 17:50
1

You can implement such a method dynamically simply by adding the property to your object at runtime in the method where you are pushing your card or deck onto the array.

For example:

var DeckStack = {
    initialize: function() {
        this.deckStack = [];
    },

    addDeck: function (name) {
        this.deckStack.push(name);
        this['deck' + this.deckStack.length] = name;    // <-- We add a method or property to the object dynamically
    }
};

DeckStack.initialize();
DeckStack.addDeck('test');
console.log(DeckStack.deck1);  // Writes 'test' to console

// This will show our new method/property as part of the object
for (var meth in DeckStack) {
    console.log(meth);
}

Maybe you are creating a Card object. If so, you would use:

var card = new Card(name); // For example
this['deck' + this.deckStack.length] = card;

and it would be available as a property on your deck object.

trousyt
  • 360
  • 2
  • 12