6

Can someone please explain this behavior to me. Lets declare a class:

Ext.define('baseClass',{
    a:null,
    ar:[],

    add:function(v) {
        this.ar.push(v);
    },
    sayAr:function() {
        console.log(this.ar);
    },

    setA:function(v) {
        this.a= v;
    },
    sayA:function() {
        console.log(this.a);
    }
});

Now I create two objects

var a = Ext.create('baseClass');
var b = Ext.create('baseClass');

Test the property

a.setA(1);
b.setA(2);

a.sayA();
b.sayA();

This outputs

1
2

Everything is OK, but

a.add(1);
b.add(2);

a.sayAr();
b.sayAr();

We get

[1,2]
[1,2]

This I don't understand. Why does it use separate "a" properties but one "ar" array for both objects. "ar" is not declared as static! I don't get it at all.

mik
  • 1,575
  • 6
  • 22
  • 33

2 Answers2

8

When you put something in the class declaration, it means it gets pushed onto the object prototype (read: it gets shared across all instances). It's not really a problem for strings/numbers/bools, but for objects and arrays you'll see this behaviour come in to effect.

If you want to have an array/object per instance, then you need to explicitly add it in the instance:

Ext.define('baseClass',{
    a:null,

    constructor: function(){
        this.ar = [];
    }

    add:function(v) {
        this.ar.push(v);
    },
    sayAr:function() {
        console.log(this.ar);
    },

    setA:function(v) {
        this.a= v;
    },
    sayA:function() {
        console.log(this.a);
    }
});
Evan Trimboli
  • 29,900
  • 6
  • 45
  • 66
  • Thank you, can you please clarify why it works different with strings/numbers/bools – mik Aug 15 '12 at 07:17
  • It doesn't make any distinction, it's just that arrays/objects are "reference" types. – Evan Trimboli Aug 15 '12 at 07:19
  • 1
    strings/numbers/bools are immutable data types. The only way to manipulate the value is to re-assign a new value to the relevant property, which in most cases will apply the new value as a member of the specific instance (`this.a = "mystring"`). The prototype (shared) will remain untouched. – mistaecko Aug 15 '12 at 07:40
3

That's because of this bit here:

Ext.define('baseClass',{
   a:null,
   ar:[], <--------------------------- you're instantiating an array object!

To make it clearer, the above code is equivalent to:

Ext.define('baseClass',{
   a:null,
   ar:new Array(),

So both objects share the same array because the object constructor only copies the reference to the array not the full array object.

Not sure how Ext.js handles constructors/initializers but you need to create the array during object construction not when you declare it....

OK, Googling gave me this:

Ext.define('baseClass',{
    constructor: function () {
        this.ar = [];
    },

That should solve your problem.

slebetman
  • 109,858
  • 19
  • 140
  • 171