首页 » 编写高质量代码:改善JavaScript程序的188个建议 » 编写高质量代码:改善JavaScript程序的188个建议全文在线阅读

《编写高质量代码:改善JavaScript程序的188个建议》建议81:原型域链不是作用域链

关灯直达底部

prototype是一种模拟面向对象的机制,它通过原型实现类与实例之间的继承关系并进行管理。以prototype机制模拟继承机制是一种原型继承,它也是JavaScript的核心功能之一。但是,prototype的真正价值在于它能够以对象结构为载体,创建大量的实例,这些实例能够在构造类下实现共享。也正因为如此,很多人利用prototype的这个特性模拟对象的继承机制。

protoype原型域可以允许原型属性引用任何类型的对象。因此,如果在protoype原型域中没有找到指定的属性,那么JavaScript将会根据引用关系,继续向外查找protoype原型域所指向对象的protoype原型域,直到对象的prototype域为它自己,或者出现循环为止。下面这个示例演示了对象属性查找的prototype规律。


function a(x){//构造函数a

this.x=x;

}

a.prototype.x=0;

function b(x){//构造函数b

this.x=x;

}

b.prototype=new a(1);//原型对象为构造函数a的实例

function c(x){//构造函数c

this.x=x;

}

c.prototype=new b(2);//原型对象为构造函数b的实例

var d=new c(3);

alert(d.x);//3

delete d.x;

alert(d.x);//2

delete c.prototype.x;

alert(d.x);//1

delete b.prototype.x;

alert(d.x);//0

delete a.prototype.x;

alert(d.x);//undefined


原型链可以帮助我们更清楚地认识JavaScript面向对象的继承关系。每个对象实例都可以访问它的构造器的原型,把这种层层指向父原型的关系称为原型链(prototype chain),如图4.5所示。

图 4.5 原型链检索示意图

在JavaScript中,一切都是对象,函数是第一型。Function和Object都是函数的实例。构造函数的父原型指向Function的原型,Function.prototype的父原型是Object的原型,Object的父原型也指向Function的原型,Object.prototype是所有父原型的顶层。


Function.prototype.a=function{//Function原型方法

alert("Function");

}

Object.prototype.a=function{//Object原型方法

alert("Object");

}

function f{//构造函数f

this.a="a";

}

f.prototype={//构造函数f的原型方法

w:function{

alert("w");

}

}

alert(f instanceof Function);//true,说明f是Function的实例

alert(f.prototype instanceof Object);//true,说明f的原型也是对象

alert(Function instanceof Object);//true,说明Function是Object的实例

alert(Function.prototype instanceof Object);//true,说明Function的原型是Object的实例

alert(Object instanceof Function);//true,说明Object是Function的实例

alert(Object.prototype instanceof Function);//false,说明Object.prototype是所有父原型的顶层


原型的引用关系也容易带来副作用。改变某个原型上的引用类型的属性值,将会影响该原型作用的所有实例对象。很多时候这种动态影响会给程序带来安全隐患。


function a{//构造函数a

this.x=;

}

function b{//构造函数b

}

b.prototype=new a;//构造函数b的原型指向a的实例

var f1=new b;

var f2=new b;

f1.x.push(1);

alert(f2.x);//1,说明实例f2的x属性值也受到影响


上面的示例演示了原型对于不同实例的影响。构造函数a中的x属性值为数组,该数组是引用类型的数据,而构造函数b的原型引用a的实例,于是直接引用了数组的指针,从而导致了实例之间相互影响的这种现象。