一、原型与原型链
想要了解面向对象中的原型链,我们就要先了解什么是组成原型链的原型。
在Javascript中,原型也是一个对象,通过原型可以实现对象的属性继承,Javascript的对象中都包含了一个Prototype内部属性,这个属性所对应的就是该对象的原型。
在Javascript中,包含一个“constructor”属性,这个属性对应创建所有指向该原型的实例的构造函数。
//封装 function Person(_name,_age,_sex){ this.name=_name; this.age=_age; this.sex=_sex; } //原型 Person.prototype={
constructor:Person, info:function(){ console.log("My name is "+this.name); }, se:function(){ console.log("I‘m a"+this.sex); } }
var per=new Person("Lihua",18,"boy");
console.log(per.constructor);
per.info();
在上面的这段代码里,首先构造函数,然后再写这个对象的原型,我们在声明一个新对象的时候,使用constructor可以查看新new的对象的构造函数。
使用per.info()我们就调用了原型里的info属性。
二、原型链
我们知道在面向对象里每个对象和原型都有原型,对象的原型指向原型对象,为父的原型又指向父级的父级,这种原型一层一层连接起来就构成了原型链。
在了解原型链之前,我们还需要了解原型的继承。
1 //封装 2 function Dog(_variety,_age,_sex,_color){ 3 this.variety=_variety; 4 this.age=_age; 5 this.sex=_sex; 6 this.color=_color; 7 } 8 //原型 9 Dog.prototype={ 10 vari:function(){ 11 console.log("品种:"+this.variety); 12 }, 13 col:function(){ 14 console.log("颜色:"+this.color); 15 } 16 } 17 //构造函数继承 18 function Smalldog(_variety,_age,_sex,_color,_height){ 19 Dog.call(this,_variety,_age,_sex,_color); 20 this.height=_height; 21 } 22 var Mydog1=new Smalldog("金毛",7,"男孩","黄","30cm"); 23 console.log(Mydog1.height); 24 //原型继承 25 Smalldog.prototype=new Dog(); 26 Smalldog.prototype.hit=function(){ 27 console.log(this.height); 28 } 29 var Mydog2=new Smalldog("金毛",7,"男孩","黄","30cm"); 30 console.log(Mydog2.age,Mydog2.height); 31 Mydog2.hit();
首先我们在1~16行代码封装了一个构造函数和原型,我们再在17~23行把Dog这一类的属性继承过来,也就是构造函数继承,接下来就是要讲的原型的继承。
我们让Smalldog的原型等于Dog的原型,然后再给Smalldog的原型新添加一个hit属性,这个过程就是Smalldog继承了它父级的属性,并且新添加了属于自己的属性hit。
新建一个对象之后我们来查看一下它的hit属性,我们就可以看到,Smalldog不仅有Dog原型中的vari和col属性,也有hit属性。
上面那么多代码中,最关键的就是下面这段代码,使用prototype来实现原型的继承。
Smalldog.prototype=new Dog(); Smalldog.prototype.hit=function(){ console.log(this.height); }
三、原型链
我们使用原型继承一层一层的构造原型,还是拿上面那段代码来举例。
1 //封装 2 function Dog(_variety,_age,_sex,_color){ 3 this.variety=_variety; 4 this.age=_age; 5 this.sex=_sex; 6 this.color=_color; 7 } 8 //原型 9 Dog.prototype={ 10 vari:function(){ 11 console.log("品种:"+this.variety); 12 }, 13 col:function(){ 14 console.log("颜色:"+this.color); 15 } 16 } 17 //构造函数继承 18 function Smalldog(_variety,_age,_sex,_color,_height){ 19 Dog.call(this,_variety,_age,_sex,_color); 20 this.height=_height; 21 } 22 var Mydog1=new Smalldog("金毛",7,"男孩","黄","30cm"); 23 console.log(Mydog1.height); 24 //原型继承 25 Smalldog.prototype=new Dog(); 26 Smalldog.prototype.hit=function(){ 27 console.log(this.height); 28 } 29 var Mydog2=new Smalldog("金毛",7,"男孩","黄","30cm"); 30 console.log(Mydog2.age,Mydog2.height); 31 Mydog2.hit();
当我们想调用某个属性的时候,比如Mydog2.col(),它首先会在Mydog2的构造函数里寻找这个属性,再到Mydog2的原型里去寻找,如果Mydog2原型里还是没有这个属性,那么就会去原型对象的原型里也就是Dog的原型里去寻找,如果最终的父级的原型里(object.prototype)里依旧没有这个属性,那么就会打印出null。
这样一条查找属性的路径和方法,就叫做原型链。
四、总结
原型链:
①在访问对象的某个成员的时候会先在对象中找是否存在。
②如果当前对象中没有就在构造函数的原型对象中找。
③如果原型对象中没有找到就到原型对象的原型上找。
④知道Object的原型对象的原型是null为止。