js 原型链与原型掐死理解

257 阅读3分钟

关于js原型链的问题一直是很多大厂喜欢的面试内容,网上收到的答案大多如出一辙,生怕你看懂,这里整理了一份给你看得懂的,看不懂请自掐

首先先上一幅图,后面来解释这图的具体内容

image.png

首先需要先了解三条原则:

1.在js中,万物皆是对象,包括函数。(所有)

2.所有对象都有一个共同的祖先,Object{}。(就像人类的Lucy,但是Lucy来源于哪里?不知道。这个不知道在道家就叫做无,js中叫做null, 没错Object._proto_的值就是null)

image.png

3.所有的对象都有一个共同属性_proto_,指向该对象的构造函数的prototype。(类似于所有人都有一半的染色体来自父亲的小蝌蚪,这一部分会决定你的某些特征)

结合图,来谈谈原型链

1.先来看一个函数:

function Person () {}

单独看这个对象(前面提到js中万物都是对象),同时也是一个函数。我们这里将函数分为两类:普通函数和构造函数。构造函数的意思指的是他已经用来构造了其他对象。类似于我们的父母,在没有我们父母之前和成为父母之后,身份发生变化,本质是不变的。所以其实所有函数都是可以成为构造函数的。

2:当这个函数构造了一个新对象

let p = new Person()

当这个语句执行后,意味着前面的Person已经初为人父,所以现在他是构造函数。所有的函数也都有一个特殊标记--prototype(又叫原型对象),因为他也可能会是一个构造函数,里面保存了自己的各个属性。就像每个人都可能会成为父母,而且有一套基因存在,决定着你的孩子会成为什么样的人。而你的孩子保留着这部分基因,拥有这些片段,也可以使用这些特征。即对象可以使用构造函数prototype的属性,所以有时候我们查找特定属性的时候,我们先去这个对象里去找,如果没有的话就去它的原型对象里面去,如果还是没有的话再去向原型对象的原型对象里去寻找...... 这个操作被委托在整个原型链上,这个就是我们说的原型链了

3.在上图中来看

我们这里的Foo就是一个构造函数,他存在着一个_proto_属性,指向他的构造函数的prototype,即图中标示的Function.prototype。对应遗传图谱中,父亲的部分特征来源于祖辈基因。而Function.prototype本身也是一个对象,所以也存在着自己的_proto_,指向了Object.prototype也是就我们开头举例用的Lucy,而Lucy来源我们不知道。对应这里,就是null。 Foo.prototype保存了自己的所有的属性,同时也有自己的_proto_属性,指向了构造自己的函数的原型对象,即这里的Object.prototype。我们的Lucy。

4.constructor属性

对于被一个函数而言,在prototype中会存在一个constructor属性,指向构造函数本身。

总结

所谓的原型链,类似于我们的遗传图谱,通过不停的寻找父辈,可以找到自己的某一个基因什么时候突变出来的。而原型链就是通过_proto_不停寻找构造函数的prototype,最终找到自己需要的属性。