原型和原型链
每个函数都有一个 prototype 属性,它是一个对象,称为原型对象。当创建函数的时候,会默认添加 prototype 这个属性。
可以通过 console.dir() 来输出函数的属性。
每个对象都有一个 __proto__ 属性,它被称为隐式原型,用来指向该对象的构造函数的原型对象。
function Test() { this.name = 'Dnzzk2'}
console.dir(Test)
const test = new Test()
console.log(test.__proto__ === Test.prototype) // trueconsole.log(Test.prototype.__proto__ === Object.prototype) // trueconsole.log(Object.prototype.__proto__ === null) // true
console.log(test.__proto__.constructor === Test) // trueconsole.log(test.__proto__.constructor === Test.prototype.constructor) // trueconsole.log(Test.prototype.constructor === Test) // true原型链的本质就是 __proto__ 指向构造函数的 prototype ,因为 Test.prototype 本身也是个对象,所以它的构造函数是 Object ,那么 Test.prototype 的隐式原型会指向 Object.prototype
,最终 Object.prototype.__proto__ 会指向 null ,不然就会出现生与死,轮回不止的情况。
原型对象 prototype 里面有一个 constructor 属性,这个属性表示对应的构造函数,一般是指向自己。
只有 __proto__ 的 constructor 属性会指向对应的构造函数,因为 test.__proto__ === Test.prototype ,所以 test.__proto__.constructor === Test.prototype.constructor 也就是 test.__proto__.constructor === Test
函数实际上是个功能完整的对象,本质是 Function 实例。打印 Test.__proto__ 的时候,会发现它的 constructor 指向 Function ,所以 Test.__proto__ === Function.prototype ,
Function.prototype 是个原型对象,所以又回到了 Object ,再到 null 。
其实挺绕的,特别是 constructor 属性,但我们只要知道 __proto__ 和 prototype 的关系,知道它会不停的往上查找,直到找到该方法,或者到 null 就可以了。