本文解析JavaScript中new操作符创建对象时,实例与原型链上constructor属性的关联机制。通过示例说明b.constructor的查找过程及覆盖行为,并分析Taobao kissy框架中利用该机制实现继承的代码逻辑,澄清对原型构造函数指向的常见误解。
new操作符与constructor属性的基本关系
在JavaScript中创建对象实例时:
例如定义一个构造函数:function BB(a){ this.a="kkk" }
执行var b=new BB();后,实例b会继承BB构造函数prototype属性所指向的原型对象;该原型对象包含一个constructor属性,它指向BB这个构造函数本身;因此,表达式alert(b.constructor==BB.prototype.constructor)返回true。
这里的“继承”机制并非简单的赋值A=B,而是通过原型链查找实现的:当访问b.constructor时,先检查实例b自身是否有该属性,若无则沿原型链查找;若手动添加b.constructor="ccc";:
再次执行alert(b.constructor==BB.prototype.constructor)将返回false,因为实例b上的constructor属性覆盖了原型链上的查找结果,而BB.prototype.constructor仍然指向BB函数;
kissy框架中的继承实现分析
以Taobao的kissy框架中的继承实现为例:
相关代码如下:
O = function (o) {
function F() {
}
F.prototype = o;
return new F();
},
sp = s.prototype,
rp = O(sp);
r.prototype = rp;
//alert(r.prototype.constructor==sp.constructor)
rp.constructor = r;
//alert(r.prototype.constructor==sp.constructor)
r.superclass = sp;起初容易误解这种反复调用和赋值的过程,实际上这是通过手动修正原型链上的constructor属性来维持正确的构造函数引用。