JS中的原型与原型链

335 阅读2分钟

js中的原型与原型链是个老生常谈的问题了,也是一个很经典的面试题。

chatgpt的解释:当访问一个对象的属性或方法时,JavaScript 引擎首先在对象本身查找,如果找不到,则会沿着原型链向上查找,直到找到该属性或方法或到达原型链的顶部(即 Object.prototype)。这种层级关系就是原型链。通过原型链,对象可以访问原型对象中的属性和方法。

那这个链是怎么链起来的呢?核心思想就是对象的__proto__等于构造函数的prototype,是不是有点云里雾里,别急下面我们来看一个例子:

截屏2023-07-18 下午5.21.43.png

当我们访问obj.gender时发生了什么呢?

1、先去查询obj本身是否有gender这个属性,现在obj本身没有这个属性,所以会继续向上查找。

2、查询obj.__proto__是否有gender这个属性,刚刚我们说过了,对象的__proto__等于构造函数的prototype, 所以obj.__proto__就等于Person.prototype,也就是说我们在Personal.prototype上查找gender这个属性,显而易见是"女"。

那如果此时我们访问的是obj.address会发生什么呢?(前两步是一样的)

1、先去查询obj本身是否有address这个属性,现在obj本身没有这个属性,所以会继续向上查找。

2、查询obj.__proto__也就是Personal.prototype是否有address这个属性,现在也是没有的,所以会继续向上查找。

3、查询Personal.prototype.__proto__ 是否有address这个属性,Personal.prototype.__proto__ 是什么?Personal.prototype本身是一个对象,对象的__proto__等于构造函数的prototype,所以Personal.prototype.__proto__等于 Object.Prototype。Object.Prototype上显而易见的也没有address这个属性,但是此时已经到了原型链的顶部,流程over.

综上:我们总结出了一条完整链路obj->Person.Prototype->Object.prototype(Person.Prototype.__proto__)中间如果已经查询到该属性则流程不会继续。

相信你对本文的核心理念已经很清楚了,那接下来我们来考虑一下这个问题。Object和Function作为js基石的两大构造函数,二者有什么关系呢?例如Object.__proto__Function.__proto__Function.prototype.__proto__之间存在某种依赖关系吗。

接下来我用一个图来表达自己的观点WechatIMG22.jpg

上图主要表达了几个概念

  • Object.__proto__ === Function.prototype
  • Function.__proto__=== Function.prototype
  • Function.prototype.__proto__=== Object.prototype

实践是检验真理的唯一标准,让我们来验证一下。

image.png

经过验证我们上面的理解是正确的,让我们来一一解读下上面的几条结论。

  • Object.__proto__应该等于它构造函数的prototype,Function是一切构造函数的基石,所以Object.__proto__等于Function.prototype

  • Function.__proto__应该等于它构造函数的prototype,Function是一切构造函数的基石,所以Function.__proto__也等于Function.prototype

  • Function.prototype.__proto__应该等于它构造函数的prototype,Function.prototype.__proto__在上面的图片中我们可以看到它本质上是一个对象,所以Function.prototype.__proto__等于Object.prototype