prototype和__proto__

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的话你甚至如此看到:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值