Edge浏览器中原型链的问题

80 阅读2分钟

初现端倪

基于我之前对原型链的认知,当我创建一个函数后一直认为原型链应该是这样的:

image.png 函数是Function的实例,且本身的__proto__属性指向Function.prototype,而Function.prototype是Object的实例,所以Function.prototype的__proto__指向Object.prototype。

毕竟我在创建一个对象时,也应该是这套逻辑。

let obj1 = {name:'Ton',sayName: function(){console.log(this.name)}}
console.dir(obj1)                       //▶Object
console.log(obj1.__proto__)             //▶{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
console.log(typeof obj1.__proto__)      //object

原型链大概长这样:

image.png

但当我看到浏览器的devTools的输出时:

image.png

Object.[[prototype]](__proto__),指向Object.prototype, 而Object.prototype的__proto__本应指向null,但此时却又指向一个Object,我:???

排查问题

通过输出obj1.__proto__,如下所示:

let obj1 = {name:'Ton',sayName: function(){console.log(this.name)}}
console.dir(obj1)
console.log(obj1.__proto__)

image.png

这个倒是正常的,Object.prototype的__proto__ 指向null。应该是edge浏览器的原因,否则的话原型链就变成这样了:

image.png

但也发现了另外一个问题使用console.log( typeof obj1.constructor)之后 给出的结果是个function,那既然是function那就说明Object也是Function的实例。

let obj1 = {name:'Ton',sayName: function(){console.log(this.name)}}
console.dir(obj1)                       //▶Object
console.dir(obj1.constructor)           //▶f Object()
console.log(obj1.constructor)           //ƒ Object() { [native code] }

于是当我再次输出一个函数并理解他的原型链时:

function afunc(aaa){
  console.log('hi',aaa);
}
console.dir(afunc)

image.png

这个原型链第一步是没问题的,但是后面不禁问edge你搞什么鬼啊,Function.prototype.__proto__ 的prototype怎么又指向了Object.prototype,而第二次指向的Object.prototype的__proto__属性最终指向了null。

翻了翻mdn的文档,大致可以理解为 __proto__

查阅了众多资料后开始理解这句话 :[[prototype]]是对象的属性,__proto__是原型对象的属性

函数是一个对象,因此afunc是一个对象,所以就有[[prototype]],且该属性指向构造函数Function的原型,Function.prototype,同时Function.prototype是Object的实例,因此他也是一个对象,也有[[prototype]]属性,且指向Object.prototype, 按照我以前的理解,原型链到此就应该结束了,Object.prototype是个原型,他的————ptoto——-指向null,但其实并不是。

如果看过输出一个 Obj1.constrtuctor就知道,Object()也是一个构造函数,那么Object就是这个构造函数的实例,所以这个指向倒是正常的状态。