初现端倪
基于我之前对原型链的认知,当我创建一个函数后一直认为原型链应该是这样的:
函数是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
原型链大概长这样:
但当我看到浏览器的devTools的输出时:
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__)
这个倒是正常的,Object.prototype的__proto__ 指向null。应该是edge浏览器的原因,否则的话原型链就变成这样了:
但也发现了另外一个问题使用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)
这个原型链第一步是没问题的,但是后面不禁问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就是这个构造函数的实例,所以这个指向倒是正常的状态。