0

I'm confused by the following scoping in JavaScript. I have a global object Rummy to which I then attach a Manager object.

The confusion is in calculate, where I store the player's current cards in a local variable var cards. I push a card into cards, but somehow this modifies the total cards in this.current_player.cards.

Why is this?

(function () {
    window.Rummy = window.Rummy || {};
})();

(function () {
    Rummy.Manager = Rummy.Manager || {};

    Rummy.Manager = (function () {
        var api = {},

        api.init = function () {
            this.players = createPlayers();
            this.current_player = this.players.mainPlayer;
            this.deck = [//some card objects in here];
            this.calculate(this.deck[this.deck.length-1]);
        };

        api.calculate = function (card) {
            // Create a new variable to store player's cards as to not modify the player's current cards...
            var cards = this.current_player.getCards(); 
            console.log('A: total cards', this.current_player.getCards());
            cards.push(card);
            console.log('B: total cards', this.current_player.getCards());
        };

        return api;
    })();
})();   

(function () {
    Rummy.Manager.init();
})();

this.current_player.getCards(); initial total: 7

A's output: 8 cards
B's output: 8 cards

If I comment out cards.push(AI_card);:

A's output: 7 cards
B's output: 7 cards

If I'm declared var cards and only modifying the new array, why is it changing the player's cards array?


Player Class if needed:

var Player = function(manager, canvas, args) {
       this.cards = [];
       ...
};

Player.prototype = {

    constructor: Player,

    setCards : function (card) {
        this.cards.push(card);
    },

    getCards : function () {
        return this.cards;
    },
};
user3871
  • 12,432
  • 33
  • 128
  • 268
  • 1
    There is no "new array" like you're assuming. `getCards` returns the same array reference. If you want to return a shallow copy, you could do something like `return this.card.slice(0);` – Evan Trimboli Dec 17 '15 at 03:35
  • @EvanTrimboli Is there a way to pass by value and not reference? – user3871 Dec 17 '15 at 03:36
  • @EvanTrimboli where would I return `return this.card.slice(0)` from? From Player class instead of `return this.cards`? – user3871 Dec 17 '15 at 03:37
  • If "by value" means create a shallow clone, then you need to do that manually. – Evan Trimboli Dec 17 '15 at 03:37
  • They are passed by value, it just so happens that the value is the object reference. – MinusFour Dec 17 '15 at 03:38
  • @Growler JavaScript actually does pass-by-value, it's just the [value is a reference itself](http://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language) . – Spencer Wieczorek Dec 17 '15 at 03:38
  • @EvanTrimboli Is this a JavaScript thing? I'm coming from Java where I was used to using getters as such to simply return a shallow copy of the value when setting a new variable, which wouldn't modify the original value – user3871 Dec 17 '15 at 03:40
  • I haven't done a great deal of Java but I'm pretty sure that's not the case. If you return a list from some method it doesn't automatically create a copy. – Evan Trimboli Dec 17 '15 at 03:42

0 Answers0