JavaScript__proto__原型链深入分析
JavaScript__proto__原型链深入分析
http://blog.****.net/irelandken/article/details/7297490
JavaSctipt之prototype原型深入分析: prototype的属性是副本,引用,还是固定的查找方式?>>
,我们已经得出结论:从自身延原型链向上查找的方式:
访问对象object.xxx的属性时,如果object自己没有xxx属性,则向上延原型链查找,如果找到,则输出,没找到,则输出undefined.
PS: 因为每个对象和原型都有一个原型(注:原型也是一个对象 ),对象的原型指向对象的父,而父的原型又指向父的父,我们把这种通过原型层层连接起来的关系撑为原型链。这条链的末端一般总是默认的对象原型。
现在我们思想一下,在原型链上,是靠什么来找到原型链的上一个结点的呢??
查询资料后,得出:
每个对象都有一个__proto__属性,原型链上的对象正是依靠这个__proto__属性连结在一起的!
1)下面,我们先测试一下"__proto__是否指向实例对象的原型prototype对象的引用":
//
- <script type="text/javascript">
- var Person = function()
- {
- };
- //Person.prototype 是一个仅含一个方法的对象
- Person.prototype.getInfo = function()
- {
- alert("username: "+this.username);
- };
- //建一个person实例
- var person = new Person();
- person.username = "zhangsan";
- person.getInfo();
- //判断__proto__是否引用 Person.prototype
- if(person.__proto__ == Person.prototype)
- {
- alert("__proto__的确是指向其原型对象的引用!");
- }
- </script>
输出:
username: zhangsan
__proto__的确是指向其原型对象的引用!
//
实例person的__proto__属性的确是引用了Person.prototype对象!,如图:
结论:
[实例].__proto__是指向其原型对象的引用!
2)下面,我们利用__proto__来模拟一下原型链的继承,来再次验证__proto__的作用:
//
- <script type="text/javascript">
- var Shape_prototype = {
- getArea:function()
- {
- return "area: "+this.area;
- }
- };
- var Retangle_prototype = {
- getEdge:function()
- {
- return "edge: "+this.edge;
- }
- };
- var retangleIns = {
- area : 20,
- edge : 4
- };
- //因为所以对象都继承于Object,所有原型链的顶端就是Object.prototype;
- if(
- (Shape_prototype.__proto__ == Object.prototype) &&
- (Retangle_prototype.__proto__ == Object.prototype) &&
- (retangleIns.__proto__ == Object.prototype)
- )
- {
- alert("所有对象都继承于Object,原型链的顶端就是Object.prototype");
- }
- //此时,retangleIns实例还没有getArea和getEdge方法,不能执行
- alert("原型链连接前,retangleIns.getArea = " + retangleIns.getArea);
- alert("原型链连接前,retangleIns.getArea = " + retangleIns.getEdge);
- //模拟原型链: 将3个对象连接成一条原型链!
- //Shape_prototype <---__proto__--- Retangle_prototype <---_proto__--- retangleIns
- Retangle_prototype.__proto__ = Shape_prototype;
- retangleIns.__proto__ = Retangle_prototype;
- //原型链连接后,getArea和getEdge方法成功执行
- alert("原型链连接后,retangleIns.getArea() = " + retangleIns.getArea());
- alert("原型链连接后,retangleIns.getArea() = " + retangleIns.getEdge());
- </script>
输出:
所有对象都继承于Object,原型链的顶端就是Object.prototype
原型链连接前,retangleIns.getArea = undefined
原型链连接前,retangleIns.getArea = undefined
原型链连接后,retangleIns.getArea() = area: 20
原型链连接后,retangleIns.getArea() = edge: 4
//
如图:
原型链连接前:
分析: 原型链连接前,retangleIns对象,Retangle_prototype对象,Shape_prototype对象 并无直接关系,因为这些对象都是Objecgt类型的实例,所以这些对象的__proto__属性引用了Object.prototype对象!
而此时retangleIns.getArea,retangleIns.getEdge当然是undefined!
原型链连接后:
分析:
Retangle_prototype.__proto__ = Shape_prototype;
retangleIns.__proto__ = Retangle_prototype;
以上两句执行后,3个对象就通过__proto__属性连接在一起,形成一条原型链!
而retangleIns.getArea() 和retangleIns.getArea()的执行成功,更充分证明了:
每个对象都有一个__proto__属性,原型链上的对象正是依靠这个__proto__属性连结在一起的!
对于原型链上的一个对象obj,那么访问obj.xxx属性(方法也是属性)的过程是: 如果自身有xxx属性,则访问它,如果没有,就通过__proto__属性找到其原型链的上一级原型对象,看它有没有xxx属性,如此递归查找,直至找到xxx属性或到了原型链顶端Object.prototype对象为止!
在此,引用一下<<酷壳网陈皓:再谈JavaScript面向对象编程>>对__proto__的解释:
__proto__成员严格的说这个成员不应该叫这个名字,__proto__是Firefox中的称呼,__proto__只有在Firefox浏览器中才能被访问到。做为一个对象,当你访问其中的一个成员或方法的时候,如果这个对象中没有这个方法或成员,那么Javascript引擎将会访问这个对象的__proto__成员所指向的另外的一个对象,并在那个对象中查找指定的方法或成员,如果不能找到,那就会继续通过那个对象的__proto__成员指向的对象进行递归查找,直到这个链表结束。
PS: 在Chrome也可以使用__proto__属性的!
参考: