原型链
在创建一个函数时,就自动为该函数添加一个prototype属性,
该属性指向原型对象,默认情况下,该对象中只包块一个constructor属性,
它是一个指向prototype属性所在函数的指针。
var Person = function () {};
var p = new Person();
我们来看看这个new究竟做了什么?我们可以把new的过程拆分成以下三步:
<1> var p = {}; //创建一个空对象p <2> p.__proto__ = Person.prototype; //修改p的__proto__属性指向,指向Person的prototype <3> Person.call(p); //修改Person对象的this指针,指向对象p下面来个例子理解下所谓的原型链
var Person = function(name){ this.name = name; } Person.prototype.say = function(){ alert(this.name); } var p = new Person('Jack'); p.say();
原型链通过__proto__维系
那么__proto__是什么?
每个对象都会在其内部初始化一个属性,就是__proto__,当我们访问一个对象的属性时,如果这个对象内部不存在这个属性(本地属性),那么它就会去__proto__里找这个属性。而这个__proto__同样是一个对象,又会有自己的__proto__,于是就这样一直构造下去,直到最后一个对象的__proto__属性为null,就形成了我们平时所说的原型链。
查找顺序
每个对象都有一个原型对象,由于原型对象本身也是对象,根据上边的定义,它也有自己的原型,而它自己的原型对象又可以有自己的原型,这样就组成了一条链,这个就是原型链。JavaScritp引擎在访问对象的属性时,如果在对象本身中没有找到,则会去原型链中查找,如果找到,直接返回值,如果整个链都遍历且没有找到属性,则返回undefined.原型链一般实现为一个链表,这样就可以按照一定的顺序来查找
tip:
如果原型链,本地属性有相同的方法,那么会优先在本地查找并执行,原型链上的方法就不执行了。同样的,属性的查找也是这么个顺序。
下面通过两个小例子说明属性和方法查找顺序:
1>
function Foo() { this.say = function(){ alert('本地方法'); } } A.prototype.say = function() { alert('prototype方法'); } new Foo().say();很显然,alert出来的结果肯定是“本地方法”这条信息,这说明了属性和方法的查找是从本地开始的。
2>
var base = { name : "base", getInfo : function(){ return this.id + "," + this.name; } } var ext = { id : 0, __proto__ : base } console.log(ext.getInfo());// 0,base // var base = { name : "base", getInfo : function(){ return this.id + "," + this.name; } } var ext = { id : 0, name : "ext", __proto__ : base } console.log(ext.getInfo());// 0,ext前者结果为"0, base",ext中没找到name属性,就通过__proto__构成的原型链找到了base身上,正好base中有该属性,结果为"base"。
后者结果为"0,ext",那是因为首先在ext中找到了属性name,结果为"ext"。这里要注意的是,ext在调用base中的getInfo时,this指向的其实是ext对象,而不是base,因此得到的结果才会是"ext"。
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/u011700203/article/details/47281393