JavaScript__proto__原型链深入分析

JavaScript__proto__原型链深入分析


在一上篇文章<<

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__属性的!


参考:

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值