一:什么是原型链?
原型链的概述:
原型链顾名思义是一条链型的关系,有下面这一张图来形象化理解:我们知道我们创建的实例化对象都有个属性叫做__proto__(对象原型),这个属性指向的是构造函数的原型对象prototype,既然这个原型对象实质也是个对象,它也有一个对象原型__proto__的属性去指向它的构造函数的原型对象prototype,它的构造函数就是顶级构造函数Object,那同理,Object构造函数的原型对象的__proto__属性又指向谁呢?其指向最顶级null,可以发现,我们的原型对象形成了一条线(链),这就是原型链
原型链的作用:
层层逐级查找,当我们需要访问对象的某个成员(属性/方法)时,会先在实例化对象本身查找有没有,如果本身没有,但是由于其有__proto__指向其构造函数的原型对象,就回去其原型对象里找,如果还没有,其原型对象也有__proto__指向更高一级的原型对象,以此类推如果再网上还没有,就指向了null,说明没有该成员。说白了就是一个逐级查找的链式结
二:原型的 this 指向问题
原型对象中的成员的 this 指向的规则我们知道是内容的调用者,谁调用就指向谁,而原型对象的成员的调用者是实例化对象,所以我们的 this 指向也是实例化的对象,与构造函数内部的this指向相同
证明:
让原型对象中的this赋值给变量that,并调用原型对象中的方法,然后比较that与实例化对象是否相等
<script>
function Animal(name,age){
this.name=name;
this.age=age;
}
var that;
Animal.prototype.eat=function(){
console.log('我在吃午饭');
that=this;
}
var dog=new Animal('旺财',5)
dog.eat()
console.log(that===dog);
</script>
结果为true,足以证明原型对象中的this指向的是实例化对象
三:使用原型对象拓展内置对象方法
我们接触过数组对象,字符串对象等等内置对象,但里面内置好的方法并不全面,例如数组对象中并没有求和的方法.....这些内置方法都是写在其对应构造函数的原型对象里的,对此我们可以采用追加的方式拓展内置对象的方法
内置对象的方法:
内置对象方法在其构造函数的原型对象中,我们可以直接打印输出查看所有方法
<script>
console.log(Array.prototype);
</script>
拓展内置方法:
就按照上述方法追加即可,但要注意只能追加,不能用等于号添加对象的方式添加(这种会覆盖掉原有内容造成不可预知的错误,上一篇文章提到过)
<script>
Array.prototype.arr_sum=function(){
var sum=0;
for(var i=0;i<this.length;i++){
sum=sum+this[i];
}
return sum;
}
var arr1=new Array(1,2,3) //以这种形式创建数组是方便直观理解,可以var arr1=[1,2,3]
console.log(arr1.arr_sum())
console.log(Array.prototype);
</script>
我们可以发现可以调用创建添加好的方法执行数组求和,并且打印Array的原型对象的内置方法,可以看到确实被加了进去
使用原型对象为内置对象添加方法是一种非常好的选择,但是再次提醒注意:只能用点追加添加的形式,不能采用等号赋值的形式!