原型和原型链

· 2 min

每个函数都有一个 prototype 属性,它是一个对象,称为原型对象。当创建函数的时候,会默认添加 prototype 这个属性。 可以通过 console.dir() 来输出函数的属性。

每个对象都有一个 __proto__ 属性,它被称为隐式原型,用来指向该对象的构造函数的原型对象。

function Test() {
this.name = 'Dnzzk2'
}
console.dir(Test)
const test = new Test()
console.log(test.__proto__ === Test.prototype) // true
console.log(Test.prototype.__proto__ === Object.prototype) // true
console.log(Object.prototype.__proto__ === null) // true
console.log(test.__proto__.constructor === Test) // true
console.log(test.__proto__.constructor === Test.prototype.constructor) // true
console.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 就可以了。