更好的方法来调用父类方法ExtJS的

问题描述:

所有ExtJS的文档和例子我已阅读建议调用父类的方法是这样的:更好的方法来调用父类方法ExtJS的

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

我一直在使用这种模式相当长的一段时间,主要的问题是,当你重命名你的类时,你也必须改变所有对超类方法的调用。这很不方便,我经常会忘记,然后我必须找出奇怪的错误。

但阅读的Ext.extend()源,我发现,这不是我可以使用superclass()super()方法是Ext.extend()增加了原形:

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

在这段代码中重命名MyPanel别的东西很简单 - 我只是必须改变一条线。

但我怀疑...

  • 我还没有看到这个记录任何地方和旧的观念认为,我不应该依靠无证行为。

  • 我没有在ExtJS源代码中找到这些superclass()supr()方法的单个用法。为什么在你不使用它们时创建它们?

  • 也许这些方法在某些旧版本的ExtJS中使用,但现在不推荐使用?但它似乎是一个非常有用的功能,为什么你会弃用它?

那么,我应该使用这些方法吗?

+0

其实,你可以试试'this.constructor.superclass.initComponent.call(this);'? – neonski 2009-11-12 21:24:04

+0

谢谢,但这与Jabe描述的问题相同 - 它只适用于一个层次的层次结构。 – 2009-11-13 08:44:53

是的,supr()没有记录。我一直期待在ExtJS 3.0.0中使用它(一个Ext的工作人员在论坛中回复,他们已经在该版本中添加了它),但它似乎非常糟糕。

它目前没有遍历继承层次结构,而是上升一层,然后卡在这个层面上,无休止地循环并炸毁堆栈(IIRC)。所以,如果你连续有两个或更多的supr(),你的应用会中断。我在文档和论坛上都没有找到关于supr()的任何有用信息。

我不知道关于维护版本3.0.x的,因为我没有得到的支持许可证...

+0

谢谢,它确实不适用于多层次的继承层次结构。供参考:3.0.3在这方面没有任何改变。 – 2009-11-13 08:47:42

+1

仍然是Sencha Touch的案例1.1 – Vitaly 2011-05-06 13:48:33

你可以使用这个鲜为人知的Javascript功能(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); 
    } 
}); 

看到MDC documentation

编辑:其实,这是不会有initComponent的工作,因为它不是” t构造函数。我总是个人重写构造函数(尽管Ext JS示例提供了这些内容)。将继续考虑这一点。

+0

已被弃用。 – Jabe 2009-11-12 20:51:48

+3

JavaScript 1.4:弃用被调用方作为Function.arguments的一个属性,将其保留为函数的本地参数变量的属性。不一样的东西! – neonski 2009-11-12 20:56:28

+0

啊,对不起,你是对的。我把它与完全不赞成使用的'调用者'混淆了。去除被调用者将会非常混乱。 – Jabe 2009-11-12 21:12:29

下面是我用一个模式,一直想在博客了一会儿。

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); 

有很多的功能,你使用这种模式,但你不必使用所有这些

+0

不错,但是这种方法引入了很多样板代码,如果调用大量的父类方法,这可能会很好,但我通常只需要调用initComponent()的父类和没有别的,在这种情况下额外的代码是恕我直言,不值得。 – 2010-11-02 13:24:29

+0

是的,这种模式是所有的OO代码使用继承,你会调用父母的方法。在Ext中,我经常从父母处调用onRender,afterRender,beforeDestroy,因为我重写了它。 – 2010-12-23 18:49:16

+0

这太好了,谢谢!我特别喜欢这个,因为如果正确完成,它可以通过JSLint/[JSHint](http://jshint.com/)。我有一些问题_linting_ [这是来自旧Sencha教程的格式](http://www.sencha.com/learn/legacy/Tutorial:Extending_Ext_for_Newbies#Extending_Functionality)。 – blong 2012-03-08 22:21:22

我会简单地改变你的代码:

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

那方式你只保留一个你的类名称,现在$ cls的引用。只在你的类方法中使用$ cls,你会没事的。

+1

如果我将每个类包装在闭包中,此解决方案将工作。目前我没有,所以这个解决方案不起作用。也许在某一天我会,所以这可以变得可行。 – 2011-01-10 16:28:54

我想出了这个解决方案在几个小时前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; 
} 

然后,你可以这样做:

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); 
    } 
}); 

测试只(铬8.0.552.237(70801) Ubuntu 10.10) 和(Firefox 3.6.13)。

希望这有助于某人,我几乎切换到GWT。

+1

'Function.caller'和'Object .__ proto__'都是非标准的。此外,后者已被弃用。虽然,这个想法看起来很有趣。 – 2011-01-26 22:13:16

我认为这是用callParent在ExtJS 4中解决的。

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]); 
    } 
}); 
+1

+1正是我在找的:) – jrharshath 2011-09-01 07:14:52

+1

这个问题涉及到Ext JS 3.x(对于稍后可能会阅读的用户) – blong 2013-01-23 23:03:25