`
yiminghe
  • 浏览: 1434039 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

简析 Extjs 类继承

阅读更多

简化的 Ext 原型链的类设计

 

function A() {
    alert('a');
}
function B() {
    B.superclass.constructor.call(this);
}
function temp() {
}
temp.prototype = A.prototype;

//防止A 的实例属性也搞到 B 里去 ,没有意思,我们只需要 A 的 prototype 里的公共属性
//不能使用 B.prototype=A.prototype  这样的话修改 B.prototype 则 A.prototype 也变了,以及影响instanceof
//不建议 B.prototype =new A() ;这样的话 A 的实例方法也到 B.prototype 里去了
B.prototype = new temp();

//上一步后 B 的实例的构造函数属性为 A 了,
// B.prototype.constructor == A
//为了以后方便B的子类调用B的构造函数
//如 C.superclass.constructor.call(this);
//要纠正
//B 的实例 的 构造函数属性要设为 B
B.prototype.constructor = B;

//要记录 B 的父亲,便于以后调用父亲方法
B.superclass = A.prototype;

if (A.prototype.constructor == Object.prototype.constructor) {
    A.prototype.constructor = A;
}

 

简要分析:

 

1.temp 作为一个空函数,将用它创建的一个对象实例插入到原型链中。这样做可以避免创建超类的新实例,因为他可能比较庞大,而且有时超类的构造函数有一些副作用(超类实例的数据属性到子类的原型中),或者会执行一些需要大量计算的任务。

 

2.最后三行代码则用来确保超类的 prototype 的 constructor 属性已经被正确设置(即使超类就是Object类本身),在用到这个新的superclass属性调用超类的构造函数时这个问题很重要。


3.最后一行是为了如果父类的 constructor 被重置了,这时候就要设回来, 我怀疑是不是 extjs 担心 这样定义类  

 

function x() {}
x.prototype = {
    y: function() {}
};
 
这样的话  x.prototype.constructor == Object.prototype.constructor  了 ,继承 x 时需要重置 x.prototype.constructor = x, 这样才能子类 sub 继承 x 时, sub.superclass.constructor == x ,但是正确的定义应该是  

x.prototype.y=function(){} 

 

他是为了预防第一种定义原型方法吧 ,我一直觉得整个设置  

 

x.prototype={}; 

 

是不好的,它把constructor也覆盖了 ,应该是 x.prototype.y=....或者一些工具函数比如 ext的override 等等

 

 

总之上述代码完美实现了一个类原型继承链,并且可以有子类显式调用父类构造函数了。

 

PS: instanceof 问题


instanceof 表面来看是来判断是否对象是某个函数new出来的,但实际上只是在原型链的比较操作:

看个例子:

 

function p(){}
function c(){}
c.prototype=p.prototype;
function d(){}
d.prototype=p.prototype;
var a=new d();
alert(a instanceof c);

 

意外么?所以我们不建议直接

 

function p(){}
function c(){}
c.prototype=p.prototype;

 

ejohn 在一篇文章 中提到的 instanceof 机制模拟 

 

function instanceOf(object, constructor) {
  while (object != null) {
    if (object == constructor.prototype)
      return true;
    object = Object.getPrototypeOf(object);
  }
  return false;
}

function p(){}
function c(){}
c.prototype=p.prototype;
function d(){}
d.prototype=p.prototype;
var a=new d();
alert(instanceOf(a,c))


现在明白了吧。其中 getPrototypeOf 为ecmascript标准中的获得对象内部  _proto_ 属性,指向它的构造函数的 prototype.(IE没有实现哦)。

 

 

ps2 : 实例属性问题

 

function xy(){
}
xy.prototype.z={q:1};
var x=new xy();
alert(x.z.q);
//可以吧这句代码注释掉,看看前后结果
x.z={q:3};
alert(xy.prototype.z.q);
x.z.q=2;
alert(xy.prototype.z.q);

 

简要分析:

 

1.对象读取属性时,(若该属性对象本身没有) 会向类的prototype相应属性查看读取。

2.对象设置属性时,会直接修改自身的属性,和类的prototype相应属性无关。

3.x.z.q=1 读分析 :x.z 读取的是 ,(若z不存在x本身属性), 类的prototype相应属性 ,x.z.q 则设置了原型z属性的 q值。

4.x.z={q:3} 写分析: 若直接设置 x.z 则设置的是 x对象本身的属性 ,和 类的prototype相应属性z无关

 

总之是:由于原型链机制而导致的读和写的不对等性造成的。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics