JavaScript__proto__原型链深入分析

JavaScript__proto__原型链深入分析



JavaSctipt之prototype原型深入分析: prototype的属性是副本,引用,还是固定的查找方式?>>

 ,我们已经得出结论:

从自身延原型链向上查找的方式:  
访问对象object.xxx的属性时,如果object自己没有xxx属性,则向上延原型链查找,如果找到,则输出,没找到,则输出undefined.
PS: 因为每个对象和原型都有一个原型(注:原型也是一个对象 ),对象的原型指向对象的父,而父的原型又指向父的父,我们把这种通过原型层层连接起来的关系撑为原型链。这条链的末端一般总是默认的对象原型。



现在我们思想一下,在原型链上,是靠什么来找到原型链的上一个结点的呢??

查询资料后,得出:

每个对象都有一个__proto__属性,原型链上的对象正是依靠这个__proto__属性连结在一起的!


1)下面,我们先测试一下"__proto__是否指向实例对象的原型prototype对象的引用":

//

[javascript]  view plain  copy
  1. <script type="text/javascript">  
  2.   
  3. var Person = function()  
  4. {  
  5. };  
  6.   
  7. //Person.prototype 是一个仅含一个方法的对象  
  8. Person.prototype.getInfo = function()  
  9. {  
  10.     alert("username: "+this.username);    
  11. };  
  12.   
  13. //建一个person实例  
  14. var person = new Person();  
  15. person.username = "zhangsan";  
  16.   
  17. person.getInfo();  
  18.   
  19.   
  20. //判断__proto__是否引用 Person.prototype  
  21. if(person.__proto__ == Person.prototype)  
  22. {  
  23.     alert("__proto__的确是指向其原型对象的引用!");  
  24. }  
  25.   
  26.   
  27. </script>  


输出:

username: zhangsan

__proto__的确是指向其原型对象的引用!

//

实例person的__proto__属性的确是引用了Person.prototype对象!,如图:




结论: 

[实例].__proto__是指向其原型对象的引用!










2)下面,我们利用__proto__来模拟一下原型链的继承,来再次验证__proto__的作用:


//

[javascript]  view plain  copy
  1.     <script type="text/javascript">  
  2.    
  3.     var Shape_prototype = {  
  4.             getArea:function()  
  5.                 {  
  6.                     return "area: "+this.area;  
  7.                 }  
  8.             };  
  9.       
  10.     var Retangle_prototype = {  
  11.             getEdge:function()  
  12.                 {  
  13.                     return "edge: "+this.edge;  
  14.                 }  
  15.             };  
  16.       
  17.     var retangleIns = {  
  18.             area : 20,  
  19.             edge : 4  
  20.     };  
  21.       
  22.     //因为所以对象都继承于Object,所有原型链的顶端就是Object.prototype;  
  23.     if(   
  24.         (Shape_prototype.__proto__ == Object.prototype) &&  
  25.         (Retangle_prototype.__proto__ == Object.prototype) &&  
  26.         (retangleIns.__proto__ == Object.prototype)   
  27.       )  
  28.     {  
  29.         alert("所有对象都继承于Object,原型链的顶端就是Object.prototype");  
  30.     }  
  31.       
  32.     //此时,retangleIns实例还没有getArea和getEdge方法,不能执行  
  33. alert("原型链连接前,retangleIns.getArea = " + retangleIns.getArea);  
  34.     alert("原型链连接前,retangleIns.getArea = " + retangleIns.getEdge);  
  35.      
  36.      
  37.      
  38.      
  39.     //模拟原型链: 将3个对象连接成一条原型链!   
  40.     //Shape_prototype <---__proto__--- Retangle_prototype <---_proto__--- retangleIns  
  41.      
  42.     Retangle_prototype.__proto__ = Shape_prototype;  
  43.      
  44.     retangleIns.__proto__ = Retangle_prototype;  
  45.      
  46.      
  47.     //原型链连接后,getArea和getEdge方法成功执行  
  48. alert("原型链连接后,retangleIns.getArea() = " + retangleIns.getArea());  
  49. alert("原型链连接后,retangleIns.getArea() = " + retangleIns.getEdge());  
  50.      
  51.       
  52.       
  53.     </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__属性的!


参考:

<<酷壳网陈皓:再谈JavaScript面向对象编程>>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
原型链Prototype Chain)是JavaScript中实现继承的一种方式。每个对象都有一个内部属性_proto_ ,该属性指向了该对象的原型对象。原型对象也有自己的_proto_属性,指向其原型对象。实际上,原型链就是通过_proto_属性将多个对象串联起来形成的链。 原型链的工作原理是当访问一个对象属性时,如果该对象本身没有定义这个属性,则会去其_proto_属性指向的原型对象上查找该属性。如果原型对象也没有定义这个属性,则会去原型对象的_proto_属性指向的原型对象上查找,依次类推,直到找到该属性或者找到最顶层的Object对象,如果仍然没有找到该属性,则返回undefined。 通过原型链,可以实现属性的继承。当我们创建一个对象时,可以指定其原型对象,该对象就可以继承原型对象上的属性和方法。当访问一个对象属性时,如果对象本身没有定义该属性,就会去其原型对象上查找,从而实现属性的继承。 尽管原型链在实现继承上非常强大,但是如果多个对象共享同一个原型对象,那么在原型对象上的属性的修改会影响到所有的对象。因此,在使用原型链实现继承时要注意避免对原型对象属性的直接修改,可以通过在子对象中重新定义同名属性来避免这个问题。 总之,原型链JavaScript中实现继承的一种机制,通过_proto_属性将多个对象连接成链状结构。通过原型链,可以实现属性的继承,并且可以通过在子对象中重新定义同名属性来扩展或者修改继承的属性

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值