2

I have an Ext JS class that I've defined. In this class's constructor, I push a textfield onto my items array, and I add to my test string. Both the array and string are declared as empty in the class definition. However, if you try and create multiple class instances, you'll see that the items array is shared across each instance, but the string is not.

This seems odd, as I would expect the definition of the class to be used as a sort of template, so then each new class, would start from scratch. It appears this is not true, so I gather this has something to do with primitives vs objects, but I'm not entirely sure why. What's the technical explanation behind Ext JS doing this? Doesn't this in the constructor refer to that particular instance, not the actual class definition?

I'm not asking how to fix the issue... I know how to do that (declare arrays and objects inside of initComponent/constructor). I'm asking what the technical explanation behind this is. From what I gather, this isn't how ES6 classes behave, so I'm assuming this is this due to the design of the Ext JS class system.

Here's an example.

Ext.application({
    name : 'Fiddle',

    launch : function() {
        Ext.define('MyClass', {
            extend: 'Ext.panel.Panel',
            alias: 'widget.myClass',
            items: [],
            border: true,
            myTestString: '',
            constructor: function(config) {
                this.items.push({
                    xtype: 'textfield',
                    fieldLabel: 'test'
                });
                this.myTestString += 'hi';
                this.callParent(arguments);
            }
        });
        var v = Ext.create('Ext.container.Viewport', {
            defaults: {
                xtype: 'myClass',
                listeners: {
                    afterrender: function(panel) {
                        console.log(panel.myTestString);
                    }
                }
            },
            items: [{
                title: 'One'
            }, {
                title: 'Two'
            }, {
                title: 'Three'
            }]
        });
    }
});
incutonez
  • 3,241
  • 9
  • 43
  • 92

1 Answers1

3

According to Evan Trimboli over on the Sencha Forums, this is due to prototypal inheritance. Meaning, any properties added to a class's definition are treated like being added to the prototype of an object. Combined with the fact that objects are passed by reference, when we add to the array, it gets updated on the class's prototype and used in creating the next instance. It's similar to the following example:

function MyClass(item) {
  this.items.push(item);
}
MyClass.prototype.items = [];
var c1 = new MyClass(1);
var c2 = new MyClass(2);
console.log(c2.items);  // returns an array of [1, 2]

In ECMAScript 6, the class system does not allow class properties, but it apparently is being considered for ES7 (per this SO answer).

incutonez
  • 3,241
  • 9
  • 43
  • 92
  • but if we put MyClass.prototype.item = 'test', then the value will retain using code above. but not in extjs, only array and object value retain.. I still cannot understand why. – Neo Oct 23 '20 at 05:22