原型链是js内容中比较重要的一部分,原型链指函数对象(函数)与原型对象(原型)以及实例化对象之间的关联,通过prototype属性、__proto__属性以及constructor属性来实现上述三类对象之间的链接,有效的解决了重复代码的使用,提高了性能。
在我的理解上,我将原型链划分为三个部分,分别为函数对象,原型对象,以及实例化对象。每个函数对象都存在一个原型对象,而实例化对象则是通过构造函数创建出来的对象(new关键字创建或者{})。加入创建了一个构造函数person,通过构造函数person实例化了一个对象p1,代码如下:
function Person(name,age){
this.name = name;
this.age = age;
}
let p1 = new Person('小明',19);
一、函数、原型和实例化对象的创建关系
由于浏览器低层的代码,在最开始会创建一个Function函数对象,并且所有的函数对象都是由Function对象创建(Function函数除外),Function函数对象又会在一开始创建一个Object对象,所有的原型对象都是由Object对象创建出来的。实例化对象是由其对应的构造函数所创建的。
所以该原型链创建的箭头指向如下:
二、函数对象中的prototype属性
每一个函数对象,都存在这prototype属性,并且prototype的属性值为对应的原型对象的引用值。比如Function函数对象中的prototype属性指向的是Function函数对象对应的原型函数,Object函数对象中的prototype属性指向的是Object函数对象对应的原型对象。如下图所示:
三、原型对象中的constructor属性
所有的原型对象中都有一个名为constructor引用类型变量,该引用类型变量是原型对象的成员,该引用类型变量的值是对应的函数对象的引用值,即constructor指向函数对象。如下图所示:
四、对象中的__proto__属性
所有对象中都有一个名为__proto__引用类型变量,该引用类型变量是对象的成员。对象中的__proto__属性的指向分为了三种情况,
(1)Function函数对象中__proto__指向Function原型对象。
(2)Object原型对象中__proto__值为null
(3)除Function函数对象和Object原型对象之外。对象中的__proto__指向
谁创建了__protot__所属的对象,就指向谁的原型。
图示如下:
五、注意事项
至此原型链的关系已经分析完毕,还需要注意的是。
1.对象访问成员的过程:
(1)当前对象中如果有该成员就该到该成员,访问结束。
(2)当前对象中如果没有该成员,则到__proto__指向的对象中找成员,找到就结束。如果还是没有找到,又通过__proto__指向的对象中去找。
基于对象访问成员的过程,我们可以将公用的函数等数据,存放在Object函数对象的原型对象上,因为实例化的对象都可以通过__proto__属性进行访问和获取。这样大大减少了代码的冗余度,提高了性能。
2.new关键字的实现过程
(1)实例化了一个对象(也就是原型链中的实例化对象)
(2)将构造函数中的this指针,指向新创建的实例化对象
(3)然后将构造函数中的属性和方法添加到实例化对象上
(4)返回this指针(this指针的值是实例化对象的引用地址)