1

For some reason, when I have an array in my class definition, and I then use the push() function to append to my array, the array variable seems to be updated for all future objects of that class that I create.

Here is the code I'm using:

var CircleSprite = cc.Class.extend({
circles:[],
thing: "",
ctor:function(target, n, x, y) {

    this.num = n;



    //This should always print 0 whenever a new object is created, but it's storing the object from the previous creation as well
    cc.log("num circles: " + this.circles.length); 

    for(var i=0; i<n; i++)
    {
        var circleSprite = new cc.Sprite.create(res.circle);

        circleSprite.setPosition(cc.p(x, y+circleSprite.height*this.circles.length));


        this.circles.push(circleSprite); //doesn't work like I want
        //this.circles = this.circles.concat(circleSprite); works well

    }

    //This code works as expected for each object
    cc.log("this thing: " + this.thing); //prints ""
    this.thing = "hi"+n;
    cc.log("this thing: " + this.thing); //print "hi2", "hi3", etc.

},

However, when I use the concat() function instead to append, the array works as expected and is only updated for each object.

So why does push() modify the variable for all instances?

rasen58
  • 4,672
  • 8
  • 39
  • 74
  • `push` mutates the array, `concat` returns a new one (and the assignment creates an *own* property) – Bergi Nov 12 '15 at 21:58

2 Answers2

1

Because all instances refer to the same variable. push appends to an existing array, while concat creates a copy with the combined values.

This is a problem because every instance of the class is holding a reference to the same array. They each have a different variable, so you can make a copy and replace that reference, but initially they all refer to the exact same array. Objects in JS are mutable, so you can modify the array and affect every instance of the class. Strings are not, so any appending or assignment will create a copy and only a single instance will refer to that copy, so you don't see this problem.

Because you've declared the array in your class definition, it is the equivalent of a static field in Java or C/++. All instances of the class will share that same value.

To resolve this, you should declare the variable in the constructor (this.circles = []), where it will be initialized for each instance and assigned only to that particular instance.

ssube
  • 47,010
  • 7
  • 103
  • 140
  • But the thing is that I've also declared other variables in the class definition, and those seem to be local to each object which is why I was confused – rasen58 Nov 12 '15 at 21:33
  • It's because you're using an object, specifically. If you were to use a string, you could append to it or reassign it no problem, because strings are immutable and you have to create a copy each time and assign that to the field. When you use an object, you can mutate the object without copying or assigning, which is picked up by anyone else holding a reference to the same object. – ssube Nov 12 '15 at 21:37
  • Ah, okay, that makes sense So all primitive types likes ints would also be different. – rasen58 Nov 12 '15 at 21:39
  • 1
    JS doesn't have many primitive types, but strings, numbers (dynamic int/float), and booleans will are all immutable. All objects, including array and functions, will have this behavior. – ssube Nov 12 '15 at 21:41
1

In addition to the other nice answer, would like to add following description of both method's from Microsoft docs with reference links:

concat() method returns a new array comprised of the array on which it is called joined with the array(s) and/or value(s) provided as arguments.
push() method adds one or more elements to the end of an array and returns the new length of the array.

Reference:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push

Maytham Fahmi
  • 31,138
  • 14
  • 118
  • 137
  • Right, I know how concat() and push() function I just didn't know that objects declared in the class definition act as static variables – rasen58 Nov 13 '15 at 05:43
  • @rasen58 yah some time smallish thing get one confused, thx for feedback, good luck with your project. – Maytham Fahmi Nov 13 '15 at 07:36