Extjs4 源码-Ext.extend解读
程序员文章站
2022-07-15 10:19:12
...
Ext.apply(Ext, { extend: function() { var objectConstructor = objectPrototype.constructor, inlineOverrides = function(o) { for (var m in o) { if (!o.hasOwnProperty(m)) { continue; } this[m] = o[m]; } }; return function(subclass, superclass, overrides) { if (Ext.isObject(superclass)) { overrides = superclass; superclass = subclass; subclass = overrides.constructor !== objectConstructor ? overrides.constructor : function() { superclass.apply(this, arguments); }; } if (!superclass) { Ext.Error.raise({ sourceClass: 'Ext', sourceMethod: 'extend', msg: 'Attempting to extend from a class which has not been loaded on the page.' }); } var F = function() {}, subclassProto, superclassProto = superclass.prototype; F.prototype = superclassProto; subclassProto = subclass.prototype = new F(); subclassProto.constructor = subclass; subclass.superclass = superclassProto; if (superclassProto.constructor === objectConstructor) { superclassProto.constructor = superclass; } subclass.override = function(overrides) { Ext.override(subclass, overrides); }; subclassProto.override = inlineOverrides; subclassProto.proto = subclassProto; subclass.override(overrides); subclass.extend = function(o) { return Ext.extend(subclass, o); }; return subclass; }; }(), override: function(cls, overrides) { if (cls.prototype.$className) { return cls.override(overrides); } else { Ext.apply(cls.prototype, overrides); } } });
针对原型和构造器的重写,会影响到重写前所创建实例的一些重要特性-例如继承性的识别。因此这种重写通常被要求在引擎最先装入的代码中进行。令人遗憾的是,开发人员通常无法保证这一点。所以在多个JavaScript扩展框架复合使用的情况下,经常会因此而出现不可控制的局面。
function MyObject() { } var obj1 = new MyObject(); MyObject.prototype.type = 'MyObject'; MyObject.prototype.value = 'test'; var obj2 = new MyObject(); MyObject.prototype = { constructor: MyObject, //<--重写原型时应该维护该属性 type: 'Bird', fly: function() {/*...*/} } var obj3 = new MyObject(); //显示对象的属性 alert(obj1.type); alert(obj2.type); alert(obj3.type);
在这个例子中,第1~7行代码创建了obj1与obj2两个对象,由于第5~6行只进行了“原型修改”,因此根据原型继承的实质我们知道obj1与obj2是类相同的两个实例。第9~13行则将原型重写成一个新的对象。不幸的是,这种重写事实上破坏了原型继承链,其直接的结果就是:obj3与obj1、obj2完全不同-这种不同甚至直接扩展到继承关系的识别上。例如:
//(续上例) //显示false alert(obj1 instanceof MyObject); alert(obj2 instanceof MyObject); //显示true alert(obj3 instanceof MyObject);
对一个函数的原型继承技巧:
function A() { alert('a'); } //B继承A的原型 function B() { } //情况1 B.prototype = new A(); //情况2 var F = function() {}; F.prototype = A.prototype; B.prototype = new F();
情况2比情况1好的地方在于情况2没有执行alert('a')操作,当我们不希望集成过程中执行父函数的构造方法时就可以借助空函数,空函数的原型是指向复函数的原型的引用。然后子函数再继承空函数从而达到原型继承的目的。
推荐阅读
-
jQuery选择器源码解读(四):tokenize方法的Expr.preFilter
-
jQuery选择器源码解读(二):select方法
-
jQuery选择器源码解读(一):Sizzle方法
-
jQuery选择器源码解读(三):tokenize方法
-
PHP网页游戏学习之Xnova(ogame)源码解读(十一)
-
PHP网页游戏学习之Xnova(ogame)源码解读(九)
-
PHP网页游戏学习之Xnova(ogame)源码解读(五)
-
PHP网页游戏学习之Xnova(ogame)源码解读(四)
-
PHP网页游戏学习之Xnova(ogame)源码解读(七)
-
PHP网页游戏学习之Xnova(ogame)源码解读(十)