前面讲到,javascript是基于原型的面向对象语言,本篇将对javascript中原型的理解,从而理解javascript如何构建对象体系。举个例子,基于类的对象和基于原型的对象构建方式区别在于:建立“人”这对象的时候,及鱼类的方式是定义人的模型,而后按照人的模型建立一我的。基于原型的方式是经过人的基因(原型)来建立一我的。javascript
原型的由来java
全部函数都有一个原型属性,当函数被定义的时候,原型自动建立和初始化,原型的初始化值是一个对象,该对象只有一个属性:constructor,该属性指向原型相关联的的构造函数。添加给原型对象的任何属性,都会被被构造函数初始化的对象的属性。对象从类实例化而来,类定义从构造函数开始,参见类定义章节的说明。chrome
在执行操做符new的时候,构造函数的原型就被设置为构造函数的原型的值。就这样全部的对象在默认的状况下都有一个原型属性,由于原型自己也是对象,因此每一个原型自身又有一个原型(只有一种例外,默认的对象原型在原型链的顶端)。一个对象的真正原型是被对象内部的[[Prototype]]属性(property)所持有。原型属性被初始化为一个对象,ECMA引入了标准对象原型访问器Object.getPrototype(object),到目前为止只有Firefox和chrome实现了此访问器。函数
下面的代码展现了获取对象原型的方法this
var a = {}; Object.getPrototypeOf(a); //获取对象a的原型 a.__proto__; //获取对象a原型的非标准方法,原型是对象的属性 a.constructor.prototype; //经过构造函数得到对象a的原型
若是想获取基本数据类型如int、false的原型,会自动转换为其封装对象,只有对象才具备原型。spa
到这里,就能够很好地理解为何经过构造函数能够建立对象,构造函数也是函数,有一个原型属性,new一个构造函数的时候,基于构造函数的原型建立了对象实例。构造函数初始化prototype
的对象从原型哪里继承了全部的属性和方法,所以原型是放置方法和不变属性的理想的地方。code
经过下面的代码来讲明原理对象
function A() { //定义构造函数a this.width = 10; this.data = [1,2,3]; this.key = "this is A"; } A._objectNum = 0; //定义A的私有属性 A.prototype.say = function(){ alert("hello"); } //给A的原型对象添加属性 var a = new A(); //建立一个对象实例 a.say(); //调用方法
原型链 blog
由于每一个对象和原型都有一个原型(注:原型也是一个对象),对象的原型指向对象的父,而父的原型又指向父的父,咱们把这种经过原型层层链接起来的关系撑为原型链。这条链的末端通常老是默认的对象原型。和基于类的面向对象的继承同样,原型的继承实现了基于原型的对象的继承。
对象在查找某个属性的时候,会首先遍历自身的属性,若是没有则会继续查找[[Prototype]]
引用的对象,若是再没有则继续查找[[Prototype]].[[Prototype]]
引用的对象,依次类推,直到[[Prototype]].….[[Prototype]]
为undefined
(Object
的[[Prototype]]
就是undefined
)。