Skip to content

Prototype Chain

要了解原型链,首先要知道prototype__proto__

prototype

实例都有一个构造函数属性(constructor)指向构造函数,通过构造函数创建的对象拥有构造函数内部定义的属性和方法

js
function Test(name, age) {
  this.name = name
  this.age = age
}

Test.prototype.say = function () {
  console.log('say')
}

let obj = new Test('xiaoming', 20)
let obj2 = new Test('xiaohong', 21)

console.log(obj.constructor === Test) // true
console.log(obj2.constructor === Test) // true
console.log(obj.constructor === obj2.constructor) // true

在js中,每一个对象(函数也是对象)都有一个特殊的属性叫原型(prototype),它指向另一个对象,这个对象(Test.prototype)被称为原型对象,原型对象是用来共享属性和方法的

js
function Test(name, age) {
  this.name = name
  this.age = age
}

Test.prototype.say = function () {
  console.log('我能说话')
}
var obj3 = new Test('Jack', 26)
var obj4 = new Test('Rose', 25)

obj3.say() // 我能说话
obj4.say() // 我能说话
console.log(obj3.say === obj4.say) // true

__proto__

每个对象都有一个__proto__属性,被称为隐式原型

js
console.log(obj3.__proto__ === Test.prototype) // true

每个js对象的__proto__,它指向创建它的构造函数的原型对象

__proto__的意义在于为原型链查找提供方向,原型链查找靠的是__proto__,而不是prototype

prototype chain

Test.prototype当然也存在属性__proto__,那么Test.prototype.__proto__是谁呢

js
console.log(Test.prototype.__proto__ === Object.prototype) // true

所有的对象,包括构造函数的原型对象,最终都是继承自Object.prototype,这是js原型链的顶点

Object.prototype作为原型链的顶端,因此,Object.prototype.__proto__指向null,表示原型链的终点

js
console.log(Object.prototype.__proto__ === null) // true

每一个对象都有一个原型(prototype)指向另一个对象,而这个对象又存在属性(__proto__)另一个对象

当我们访问一个对象的属性时,会先在自己的属性中查找,没找到就会沿着__proto__一路向上找。最终形成一个链式结构,称为原型链

进阶

原型链机制

还记得__proto__存在的意义时为原型链查找提供方向

Function的原型

Function.prototype === Function.__proto__

按照刚才的结论,函数对象的__proto__应该指向Function.prototype(即function.prototype.__proto__ === function.prototype),但是自己指向自己没有意义。别忘记Object.prototype才是原型链的终点,指向Object.prototype能保证原型链存在终点,所以Function.prototype.__proto__ === Object.prototype

如果再深究一点,Object也是函数对象,Object.__proto__ 也会指向Function.prototype

构造函数Test也有constructor属性,这个属性指向创建该函数的构造函数;如果自己没有构造函数,会指向Function

原型链就成了这样:

在构造函数Test上访问Object.prototype中的属性时,其实是顺着Test.__proto__Function去访问的

js
function Test(name, age){
    this.name = name
    this.age = age
}
var obj = new Test('Jack', 26)
 
Object.prototype.price = 2000
 
Function.prototype.price = 300
 
Test.price // 300

Function.prototype上没有price,才会往上找到Object.prototype