ExtJs 5 & 'strict mode'

There are some good discussions on why one should or should not use the strict mode when coding in JS. I am not going to elaborate on that but rather focus on what to do to write an ExtJs class / app in strict mode.

Before going further, a bit of reading on the strict mode:

ExtJs implements its own class system and basically does not support strict mode (here, here). This is the case with ExtJs 5 too so far. But luckily it will not stop us from creating an ExtJs class with strict mode enabled.

So let's have a look at an ExtJs class with strict mode enabled class wide:

(function(){
    //Make sure strict mode is on
    'use strict';

    Ext.define('MyApp.Class1', {

        daNumber: null,

        constructor: function(config){
            //do some work
            this.daNumber = 666;
        },

        gimmeDaNumber: function(){
            return this.daNumber;
        }
    });
}());

So far so good, the class behaves as expected, so let's extend it:

(function(){
    //Make sure strict mode is on
    'use strict';

    Ext.define('MyApp.Class2', {

        extend: 'MyApp.Class1',

        constructor: function(config){
            this.callParent(arguments);
        },

        gimmeDaNumber: function(){
            //get the output off the parent first
            var no = this.callParent();
            return no + ' is the number of the beast';
        }
    });

}());

Boom. Instantiating the class above will no longer be possible with strict mode:


Remember though ExtJs class system is a good one, so even though internally ExtJs may not be strict mode ready, it already provides some functionality that will let us use the strict mode in own classes - in this case we are looking at the superclass property that provides the access to the parent class. Have a look at an excerpt from Ext.Base.extend

    var me = this,
        parentPrototype = parent.prototype,
        prototype, i, ln, name, statics;

    prototype = me.prototype = Ext.Object.chain(parentPrototype);
    prototype.self = me;

    me.superclass = prototype.superclass = parentPrototype;

All clear now, huh? So let's fix the Class2:

(function(){
    //Make sure strict mode is on
    'use strict';

    Ext.define('MyApp.Class2', {

        extend: 'MyApp.Class1',

        constructor: function(config){
            //this will not work: in strict mode access to caller is censored!
            //this.callParent(arguments);

            //but this will do just fine
            this.superclass.constructor.apply(this, arguments);
        },

        gimmeDaNumber: function(){
            //get the output off the parent first

            //this will not work
            //var no = this.callParent(arguments);

            //but this will do just fine
            var no = this.superclass.gimmeDaNumber.call(this);
            return no + ' is the number of the beast';
        }
    });
}());

Obviously the above requires typing a bit more than callParent, but... (right back at the whether or not to use strict mode discussion, aren't we ;)

A working 'beastish' (IronMaiden playing in the morning ;) app example:

(function(){
    //Make sure strict mode is on
    'use strict';

    Ext.define('MyApp.Class1', {

        daNumber: null,

        constructor: function(config){
            //do some work
            this.daNumber = 666;
        },

        gimmeDaNumber: function(){
            return this.daNumber;
        }
    });

    Ext.define('MyApp.Class2', {

        extend: 'MyApp.Class1',

        constructor: function(config){
            this.superclass.constructor.apply(this, arguments);
        },

        gimmeDaNumber: function(){
            //get the output off the parent first
            var no = this.superclass.gimmeDaNumber.call(this);
            return no + ' is the number of the beast';
        }
    });

    Ext.define('MyApp.Application', {

        extend: 'Ext.app.Application',

        launch: function () {
            //so far so good
            var c1 = Ext.create('MyApp.Class1');
            console.warn('gimmeDaNumber C1', c1.gimmeDaNumber());

            var c2 = Ext.create('MyApp.Class2',{cfg: 'cfg'});
            console.warn('gimmeDaNumber C2', c2.gimmeDaNumber());
        }
    });
}());
blog comments powered by Disqus