了解JavaScript原型链,彻底明白隐式原型调用关系

803 阅读1分钟

原型链经典图

原型链.jpg

得出结论

  1. 构造函数创建的实例的隐式原型__proto__指向构造函数显式原型prototype
  2. 函数的隐式原型__proto__指向Function.prototype
  3. 构造函数(除了Object)的显式原型prototype的隐式原型__proto__指向Object.prototype
  4. Object的隐式原型__proto__指向null
  • 特别说明

实例对象的原型链

Object实例

const obj = new Object();
// const obj = {};
obj.__proto__ === Object.prototype; // true
Object.prototype === null; // true

非Object实例

function Person(){}
const person = new Person();
person.__proto__ === Person.prototype; // true
Person.prototype.__proto__ === Object.prototype; // true
Object.prototype === null; // true

函数原型链

可能很少人说到这一点

Function构造函数原型对象的方法

  • Function.prototype.bind
  • Function.prototype.call
  • Function.prototype.apply
  • Function.prototype.toString

普通函数的原型链

  • 说明:构造函数直接调用就是普通函数
function toString() {
    return this.name;
}
const obj = {
    name: 'vien'
};
toString.call(obj); // 'vien'
toString.__proto__ === Function.prototype; // true
Function.prototype.__proto__ === Object.prototype; // true

结论

  • toStringcall方法实际是调用Function.prototype.call方法

内置构造函数显式原型上方法

const obj = {};
Object.prototype.toString.call(obj); // "[object Object]"

结论

  • 显式原型上方法的call方法实际是调用Function.prototype.call方法

继承原型链

class Grandfather { }
class Father extends Grandfather { }
class Son extends Father { }
const son = new Son();

// 实例
son.__proto__ === Son.prototype;

// 构造函数
Son.__proto__ === Father;
Father.__proto__ === Grandfather;
Grandfather.__proto__ === Function.prototype; // ①

// 类prototype(显示原型)
Son.prototype;
Father.prototype;
Grandfather.prototype;

// __proto__(隐式原型)
Son.prototype.__proto__ === Father.prototype;
Father.prototype.__proto__ === Grandfather.prototype;
Grandfather.prototype === Function.prototype;

// Grandfather直接理解为构造函数,等同于构造函数原型链
Grandfather.__proto__ === Function.prototype; // 同①
Grandfather.prototype.__proto__ === Object.prototype;