Javascript 在ExtJS中调用超类方法的更好方法
我读过的所有ExtJS文档和示例都建议调用超类方法,如下所示:Javascript 在ExtJS中调用超类方法的更好方法,javascript,extjs,extend,extjs3,superclass,Javascript,Extjs,Extend,Extjs3,Superclass,我读过的所有ExtJS文档和示例都建议调用超类方法,如下所示: MyApp.MyPanel = Ext.extend(Ext.Panel, { initComponent: function() { // do something MyPanel specific here... MyApp.MyPanel.superclass.initComponent.call(this); } }); 我已经使用这个模式很长一段时间了,主要的问题是,当你重命名你的类时,你还必须改
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中使用过,但现在不推荐了?但它似乎是一个非常有用的功能,为什么您会反对它呢
那么,我是否应该使用这些方法呢?您可以使用这个鲜为人知的Javascript功能(arguments.callee):
看
编辑:实际上,这不适用于initComponent,因为它不是构造函数。我个人总是重写构造函数(不管ExtJS示例如何建议)。我会继续考虑这个问题。是的,确实,supr()
没有文档记录。我一直期待在ExtJS 3.0.0中使用它(一名Ext工作人员在论坛上回复,他们在该版本中添加了它),但它似乎坏得可怕
它目前不遍历继承层次结构,而是上一级,然后停留在这个级别上,无休止地循环并炸毁堆栈(IIRC)。因此,如果您有两个或两个以上的supr()
,您的应用程序将中断。我在文档和论坛中都没有找到任何关于supr()
的有用信息
我不知道3.0.x版的维护版本,因为我没有获得支持许可证…这是我使用的一种模式,我打算在博客上写一段时间
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);
使用此模式可以获得许多功能,但您不必全部使用它们我只需将代码更改为:
var $cls = MyApp.MyPanel = Ext.extend(Ext.Panel, {
initComponent: function() {
// do something MyPanel specific here...
$cls.superclass.initComponent.call(this);
}
});
这样,您只保留一个类名称引用,现在是$cls。只要在类方法中使用$cls,您就可以了。我几个小时前就提出了这个解决方案,呵呵
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了。我想这在ExtJS4中通过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]);
}
});
JavaScript 1.4:已弃用被调用方作为Function.arguments的属性,保留它作为函数的局部arguments变量的属性。不一样!啊,对不起,你说得对。我把它和完全不赞成的“来电者”混淆了。删除被调用方会很混乱。实际上,您可以尝试this.constructor.superclass.initComponent.call(this)代码>?谢谢,但这与Jabe描述的问题相同-它只适用于一个层次结构级别。谢谢,它确实不适用于多个继承层次结构级别。仅供参考:在3.0.3中,在这方面没有任何变化。Sencha Touch 1.1Nice仍然是这样,但这种方法引入了大量样板代码,如果调用许多父类方法,这可能很好,但我通常只需要调用initComponent()的父类,其他什么都不需要,在这种情况下,额外的代码是不值得的。是的,这种模式适用于所有使用继承的OO代码,您可以调用父方法。在Ext中,我经常从父级调用onRender、afterRender、beforeDestroy,因为我覆盖了它。这太棒了,谢谢!我特别喜欢这个,因为如果操作正确,它可以通过JSLint/测试。我在linting方面遇到了一些问题。@ReneSaarsoo,您(或Juan Mendes)如何在这种设计中保留非静态私有方法?@b.long最简单的解决方案是让您的私有非静态函数只使用类似于privateStatic
的函数,但您必须使用privateNonStatic.call调用(this,arg1,arg2)
。不是很优雅…如果我将每个类包装在一个闭包中,这个解决方案就可以工作了。目前我没有,所以这个解决方案不起作用。也许有一天我会的,所以这可以成为可行的。函数、调用者
和对象.\uuuuu协议.\uuuu
都是非标准的。此外,后者也不推荐使用。不过,这个想法看起来很有趣。这个问题与ExtJS3.x有关(供稍后可能阅读本文的用户使用)
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]);
}
});