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的实例,于是直接引用了数组的指针,从而导致了实例之间相互影响的这种现象。