Better way to call superclass method in ExtJS

后端 未结 6 1438
梦如初夏
梦如初夏 2020-12-24 06:30

All the ExtJS documentation and examples I have read suggest calling superclass methods like this:

MyApp.MyPanel = Ext.extend(Ext.Panel, {
  initComponent: f         


        
相关标签:
6条回答
  • 2020-12-24 07:01

    I think this is solved in ExtJS 4 with callParent.

    Ext.define('My.own.A', {
        constructor: function(test) {
            alert(test);
        }
    });
    
    Ext.define('My.own.B', {
        extend: 'My.own.A',
    
        constructor: function(test) {
            alert(test);
    
            this.callParent([test + 1]);
        }
    });
    
    0 讨论(0)
  • 2020-12-24 07:05

    You could use this little known Javascript feature (arguments.callee):

    MyApp.MyPanel = Ext.extend(Ext.Panel, {
        constructor: function() {
            // Do your thing
            this.thing = 1;
    
            // Call super
            arguments.callee.superclass.constructor.apply(this, arguments);
        }
    });
    

    see MDC documentation

    Edit: Actually, this isn't going to work with initComponent because it isn't the constructor. I always override the constructor, personally (despite what Ext JS examples suggest). Will continue to think about this one a bit.

    0 讨论(0)
  • 2020-12-24 07:09

    I've came up with this solution a couple hours ago heheh...

    function extend (parentObj, childObj) {
        parentObj = parentObj || function () {};
    
        var newObj = function () {
            if (typeof this.initialize == 'function') {
                this.initialize.apply(this, arguments);
            }
        }
    
        newObj.prototype.__proto__ = parentObj.prototype;
    
        for (var property in childObj) {
            newObj.prototype[property] = childObj[property];
        }
    
        newObj.prototype.superclass = function (method) { 
            var callerMethod = arguments.callee.caller,
                currentProto = this.constructor.prototype.__proto__;
    
            while (callerMethod == currentProto[method]) {
                currentProto = currentProto.__proto__;
            } 
    
            return currentProto[method]; 
        };
    
        return newObj;
    }
    

    Then you can do:

    var A = function () { 
        this.name = "A Function!";
    };
    
    A.prototype.initialize = function () {
        alert(this.name);
    }
    
    var B = extend(A, {
        initialize: function () {
            this.name = "B Function!";
            this.superclass('initialize').apply(this);
        }
    });
    
    var C = extend(B, {
        initialize: function () {
            this.superclass('initialize').apply(this);
        }
    });
    

    Tested only with (Chromium 8.0.552.237 (70801) Ubuntu 10.10) and (Firefox 3.6.13).

    Hope this help someone, I was almost switching to GWT.

    0 讨论(0)
  • 2020-12-24 07:10

    Yes indeed, supr() isn't documented. I've been looking forward to using it in ExtJS 3.0.0 (an Ext staff member replied in the forums, they had added it in that version), but it seems horribly broken.

    It currently does not traverse the inheritance hierarchy, but rather go up one level, then gets stuck on this level, loops endlessly and blows up the stack (IIRC). So, if you have two or more supr() in a row, your app will break. I have not found any useful information on supr() in neither the docs nor the forums.

    I don't know about the maintenance releases 3.0.x, since I did not get an support license ...

    0 讨论(0)
  • 2020-12-24 07:15

    I would simply change your code to:

    var $cls = MyApp.MyPanel = Ext.extend(Ext.Panel, {
      initComponent: function() {
        // do something MyPanel specific here...
        $cls.superclass.initComponent.call(this);
      }
    });
    

    That way you only keep a single reference of your class name, now $cls. Only use $cls within your class methods and you'll be fine.

    0 讨论(0)
  • 2020-12-24 07:18

    Here's a pattern I use, and been meaning to blog about it for a while.

    Ext.ns('MyApp.MyPanel');
    
    MyApp.MyPanel = (function(){
      var $this = Ext.extend(Ext.Panel, {
        constructor: function() {
            // Using a 'public static' value from $this
            // (a reference to the constructor)
            // and calling a 'private static' method
            this.thing = $this.STATIC_PROP + privateStatic();
            // Call super using $super that is defined after 
            // the call to Ext.extend
            $super.constructor.apply(this, arguments);
        },
        initComponent: function() {
            $super.initComponent.call(this);
            this.addEvents([Events.SOMETHING]); // missing docs here
        }
      });
      var $super = $this.superclass;
    
      // This method can only be accessed from the class 
      // and has no access to 'this'
      function privateStatic() {
        return "Whatever";
      }
    
    
      /** 
        * This is a private non-static member
        * It must be called like getThing.call(this);
        */
      function getThing() {
         return this.thing;
      }
    
      // You can create public static properties like this
      // refer to Events directly from the inside
      // but from the outside somebody could also use it as
      //  MyApp.MyPanel.Events.SOMETHING
      var Events = $this.Events = {
          SOMETHING: 'something'
      }
    
      return $this;
    })();
    
    MyApp.MyPanel.STATIC_STRING = 10;
    
    //Later somewhere
    var panel = new MyApp.Mypanel();
    panel.on(MyApp.Mypanel.Events.SOMETHING, callback);
    

    There are a lot of features you get using this pattern, but you don't have to use all of them

    0 讨论(0)
提交回复
热议问题