欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

prototype和__proto__

程序员文章站 2024-03-21 11:04:58
...

prototype和__proto__

以前看的时候就对这个prototype和__proto__感到很奇怪。然后今天看了篇文章,又见到了谈论到这个话题的。

然后搜索了一下,发现这些人讲的都好复杂。。。然后就把自己的想法记录一下吧。

原型链是一个环

先说结论:__proto__维系着原型链,但是prototype才是真正的原型。__proto__指向其构造函数的prototype

结论看起来好像有点奇怪,但是其实很容易明白。

首先第一个事实,只有函数才拥有prototype属性,也可以说只有函数才具有真正的原型。这一点很容易验证Ctrl+Shift+I,打开控制台就可以查看。

第二个事实,除了undefined null以及其他字面量以外,js中所有的值实际上都是一个对象,这一点实际上应该也很容易能够明白。

这两个事实就造成了一个可以看见的现象/事实,函数既有__proto__又有prototype,而对象只有__proto__(这是很重要的一点)。

然后我们就可以很容易描述他们的继承关系了。

class Parents {
  name = "parent";
}
class Son extends Parents {
  name = "son";
}
const son = new Son();

那当我们son instanceof Parents的时候会发生什么呢?

son
 -> Son.prototype(son.__proto__)
    -> Parents.prototype (son.__proto__.__proto__) ✅找到了

你可以验证一下son.__proto__.__proto__ === Parents.prototype是否为true。

实际上,__proto__应该是内部实现,是不应该暴露出来的,但是有些浏览器默认将它暴露出来,于是就将错就错了。

但是还是存在一个问题,就是如果对象的__proto__是其构造函数的prototype,在JS中实际上函数也是一个对象,__proto__以及prototype也是一个对象,Object.prototypeFunction.prototype将原型链关闭了。那么原型链实际上就不是一个链了,而是一个闭合的环,这当然是绝对不行的。

原型链不是一个环

实际上我们如果查看一下Object.prototype.__proto__的话,他的值应该是null。这一点一样可以在浏览器控制台真实。所以这个表现告诉我们的(能够符合这个事实表现的推论是)Object.prototype对象是一个特殊的__proto__被设置称为null的对象。

Object.prototype就是原型链的终点。如果安装了firefox的话你甚至如此看到:
prototype和__proto__

当然,默认__proto__那里是一个小箭头,你需要点击一下才会把null这个值展示出来,同时你也应该注意到了getter和setter,就是getter将这个__proto__的值返回的,在chrome上你应该看不到Object.prototype__proto__属性,但是在Object.prototype上他们同样具有__proto__的getter和setter。