每一个javascript对象都有一个原型对象,这个对象在不一样的解释器下的实现不一样。好比在firefox下,每一个对象都有一个隐藏的__proto__属性,这个属性就是“原型对象”的引用。javascript
因为原型对象自己也是对象,根据上边的定义,它也有本身的原型,而它本身的原型对象又能够有本身的原型,这样就组成了一条链,这个就是原型链,JavaScritp引擎在访问对象的属性时,若是在对象自己中没有找到,则会去原型链中查找,若是找到,直接返回值,若是整个链都遍历且没有找到属性,则返回undefined.原型链通常实现为一个链表,这样就能够按照必定的顺序来查找。java
继承是OO语言中一个重要的特性和概念。许多的OO语言中都支持两种继承方式:接口继承和实现继承。数组
ECMAScript只支持实现继承,其实现继承主要是靠原型链来实现。在PHP语言中,是使用extend来实现继承。那么咱们就先来说讲原型链。函数
原型链的基本思想是利用原型让一个引用类型继承另外一个引用类型的属性和方法。this
简单回顾下构造函数、原型和实例的关系:spa
每一个构造函数都有一个原型对象,原型对象包含一个指向构造函数的指针(prototype),而实例则包含一个指向原型对象的内部指针(__proto__)。firefox
实现原型链有一种基本模式,其代码大体以下:prototype
function SuperType() { this.property = true; } SuperType.prototype.getSuperValue = function() { return this.property; }; function SubType() { this.subproperty = false; } //继承了SuperType SubType.prototype = new SuperType(); SubType.prototype.getSubValue = function() { return this.subproperty; }; var instance = new SubType(); alert(instance.getSubValue()); //false
以上代码是定义了2个类型:SuperType()和SubType(),每一个类型分别有一个属性和方法。2者的区别是SubType继承了SuperType。经过建立SuperType实例并将该实例赋给SubType.prototype。原来存在于SuperType中全部的属性和方法也都存在于SubType.prototype中了。在确立了这种继承关系后,又在SubType.prototype中添加了一个方法。指针
请看下图展现的实例以及构造函数和原型之间的关系:PS:找线画了半天没画好,先这么看吧:)code
肯定原型和实例的关系:
能够经过两种方式来肯定原型和实例之间的关系。第一种方式是使用instanceof操做符;第二种是使用isPrototypeOf()方法。
alert(instance instanceof Object); //true alert(instance instanceof SuperType); //true alert(instance instanceof SubType); //true alert(Object.prototype.isPrototypeOf(instance)); //true alert(SuperType.prototype.isPrototypeOf(instance)); //true alert(SubType.prototype.isPrototypeOf(instance)); //true
原型链的问题:
虽然很强大,能够用它来实现继承,但它也存在一些问题。最主要的问题来自包含引用类型值的原型。在经过原型来实现继承时,原型实际上会变成一个类型的实例。因而,原先的实例属性也瓜熟蒂落的变成了如今的原型的属性了。看例子吧!
虽然很强大,能够用它来实现继承,但它也存在一些问题。最主要的问题来自包含引用类型值的原型。在经过原型来实现继承时,原型实际上会变成一个类型的实例。因而,原先的实例属性也瓜熟蒂落的变成了如今的原型的属性了。看例子吧!
function SuperType() { this.colors = ["red", "green", "blue"]; } function SubType() { } //继承了SuperType SubType.prototype = new SuperType(); var instance1 = new SubType(); instance1.colors.push("black"); alert(instance1.colors); //red,green,blue,black var instance2 = new SubType(); alert(instance2.colors); //red,green,blue,black
SuperType构造函数定义了一个属性,该属性包含一个数组(引用类型值)。当SubType经过原型继承了SuperType以后,SubType.prototype就变成了SuperType的一个实例。所以也拥有了SuperType的全部属性和方法。结果SubType会共享这个colors属性,咱们经过对instance1.colors的修改,可以经过instance2.colors反映出来。
第二个问题是建立子类型的实例时,不能向超类型的构造函数中传递函数。鉴于这几点问题,实践中不多会单独使用原型链。
hasOwnProperty是判断一个对象是否包含自定义属性而不是原型链上的属性,是JS中惟一一个查找属性,但不查找原型链的函数。