js原型链解析

一、前言

  学前端的人不能不会js, 学js的人不能不懂原型链。原型链可以说是js中非常关键的一环,今天借此机会好好剖析一下原型链,也加深一下自己的理解。

二、js对象的几个属性

  在js中, __proto__和prototype是两个比较重要的属性,这两个的区别其实也非常简单。首先,每个对象都会有__proto属性,他会指向自己的构造函数的原型。而并不是每个对象都有prototype属性,只有函数才会有prototype属性,他指向自己的原型对象。原型对象上挂载的方法和属性被所有实例所共享,同时原型对象也有一个属性叫constructor,指向了构造函数即Funtion对象。在这里我们就不过多的介绍他们之间的关系了,不明白的同学可以去百度搜索一下,今天我们的重点在一张图上。相信大家在学习原型链的时候都见过这张图,今天我们的目标就是彻底理解这张图,话不多说,先上图。
在这里插入图片描述

三、图片剖析

  首先我们来看f1, f2和Foo(),Foo.prototype的关系.Foo是一个构造函数,它比f1, f2多了一个prototype属性,指向了它的原型对象。而f1, f2是Foo new出来的实例。所以f1, f2的__proto__会指向他们的构造函数的原型对象,即Foo.prototype。我们之前又说到,原型对象还有一个constructor属性,会指回原构造函数,所以它的constructor指回了Foo。如果对于这三个的关系能够理清,那么证明你已经理解了我们刚才所说的三个属性,下面我们继续。
  我们看到,Foo.prototype也有一个__proto__属性,指向了Object.prototype,这是为什么呢?因为原型对象也是一个对象,他的构造函数是Object,而__proto__属性回指向构造函数的原型对象,所以就指向了Object.prototype。所以其实Foo.prototype和两个由Object new出来的对象本质上是一样的,可以看到他们的__protot__都指向了Object.prototype。然后我们再来看Object()函数,它和它原型对象直接的关系就不用多说了,prototype属性指向了原型对象,原型对象的constructor指回了构造函数。那么为什么它的__proto__又指向了Function.prototype。道理很简单,因为它的构造函数是Function,所以自然它的__proto__会指向构造函数的原型对象即Function.prototype。而为什么Function的__proto__也指向了Function.prototype,我的理解是因为它本身也是一个函数,所以它的__proto__也指向了Function.prototype。至于Funtion.prototype的__proto__,和刚才的Object一样,他们都是一个对象,所以__proto__都指向了Object.prototype。
  最后还剩两条链没有说到,第一是Foo的prototype,很显然,Foo和Object都是构造函数,他们的构造函数都是Funtion,所以他们的__proto__都会指向Funtion.prototype。而原型链的重点就是Object.prototype,它的__proto__会指向null,这也是为什么在js中有一种万物皆对象的说法。那么到这里,对于图中的每一条链我们都已经解释清楚了,我们下面来看一段代码进行实战加深自己的理解。

四、代码实战

function Person() {}
let temp = new Person();
Person.prototype.test = "Function";
Object.prototype.test = "Object";
console.log(temp.test);
console.log(Person.test);

  大家可以想一想这到底会输出什么,我们一个个来看:
首先看temp.text,它的查找链条应该是这样的:

temp -> temp.__proto__ (Person.prototype)

  首先在temp上找,发现找不到,就会去temp的原型上找,即temp.prototype,即我们的Person.prototype。这时可以找到test属性,所以输出Funtion。
下面看Person.test,不要想当然的以为会输出Function,我们继续来看它的查找链条:

Person -> Person.__proto__(Function.prototype) -> Function.prototype.__proto__(Object.prototype)

  可以看到,我们最终找到来Object.prototype上去,所以会输出Obejct。如果觉得有疑问的小伙伴可以在Function.prototype上再加一个test属性看最终输出会变成什么样子。

五、结语

  结合代码和图片,是不是感觉对于原型链的理解清晰了很多?所以,我认为,如果你真的完全理解了这张图片,那么也就说明你已经掌握了js的原型链,希望同学们好好去看看这张图片和这段代码,早日成为一个js的老司机。

发布了24 篇原创文章 · 获赞 46 · 访问量 5146

猜你喜欢

转载自blog.csdn.net/qq_38164763/article/details/100402948