前置知识: JavaScript

原型链继承与class本质

2 minAdvanced2026/6/14

JavaScript原型链继承机制与class语法糖本质深度解析。

1. 原型链基础

1.1 原型对象

每个 JavaScript 对象都有一个内部属性 [[Prototype]],指向其原型对象:

function Person(name) {
  this.name = name;
}

Person.prototype.greet = function () {
  return `Hello, I'm ${this.name}`;
};

const alice = new Person('Alice');

alice.greet(); // "Hello, I'm Alice"
alice.hasOwnProperty('name'); // true
alice.hasOwnProperty('greet'); // false — 来自原型

1.2 原型链查找

alice → Person.prototype → Object.prototype → null

查找属性时沿原型链向上搜索,直到找到或到达 null
alice.name; // 自身属性 → 'Alice'
alice.greet; // Person.prototype → function
alice.toString; // Object.prototype → function
alice.nonExistent; // null → undefined

1.3 原型链关系

                    ┌─────────────────┐
                    │  Object.prototype│
                    │  ─────────────── │
                    │  toString()     │
                    │  hasOwnProperty()│
                    │  valueOf()      │
                    └────────┬────────┘
                             │ [[Prototype]]
                    ┌────────┴────────┐
                    │ Person.prototype │
                    │ ─────────────── │
                    │ constructor: Person│
                    │ greet()         │
                    └────────┬────────┘
                             │ [[Prototype]]
                    ┌────────┴────────┐
                    │     alice        │
                    │ ─────────────── │
                    │ name: 'Alice'   │
                    └─────────────────┘

2. 原型链继承模式

2.1 原型链继承

function Animal(name) {
  this.name = name;
}
Animal.prototype.speak = function () {
  return `${this.name} makes a sound`;
};

function Dog(name, breed) {
  Animal.call(this, name); // 借用构造函数
  this.breed = breed;
}

// 原型链继承
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.bark = function () {
  return `${this.name} barks!`;
};

const rex = new Dog('Rex', 'German Shepherd');
rex.speak(); // "Rex makes a sound" — 来自 Animal.prototype
rex.bark(); // "Rex barks!" — 来自 Dog.prototype

2.2 Object.create 原理

// Object.create 的简化实现
function objectCreate(proto, propertiesObject) {
  function F() {}
  F.prototype = proto;
  const obj = new F();
  if (propertiesObject) {
    Object.defineProperties(obj, propertiesObject);
  }
  return obj;
}

2.3 继承的完整模式

function Parent(name) {
  this.name = name;
  this.colors = ['red', 'blue'];
}
Parent.prototype.getName = function () {
  return this.name;
};

function Child(name, age) {
  Parent.call(this, name); // 第二次调用 Parent
  this.age = age;
}
Child.prototype = Object.create(Parent.prototype); // 第一次调用 Parent
Child.prototype.constructor = Child;
Child.prototype.getAge = function () {
  return this.age;
};

3. class 语法糖本质

3.1 class 声明等价转换

// class 写法
class Person {
  constructor(name) {
    this.name = name;
  }
  greet() {
    return `Hello, I'm ${this.name}`;
  }
  static create(name) {
    return new Person(name);
  }
}

// 等价的原型写法
function Person(name) {
  this.name = name;
}
Person.prototype.greet = function () {
  return `Hello, I'm ${this.name}`;
};
Person.create = function (name) {
  return new Person(name);
};

3.2 class 与 function 的区别

特性classfunction
提升不会提升(TDZ)函数声明会提升
严格模式自动启用 use strict默认非严格
不用 new 调用抛出 TypeError作为普通函数执行
prototype不可枚举可枚举
方法不可枚举可枚举
内部属性[[FunctionKind]]: classConstructor[[FunctionKind]]: normal

3.3 class 继承的本质

class Animal {
  constructor(name) {
    this.name = name;
  }
  speak() {
    return `${this.name} makes a sound`;
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    super(name); // 等价于 Animal.call(this, name)
    this.breed = breed;
  }
  bark() {
    return `${this.name} barks!`;
  }
}

extends 做了两件事:

// 1. 设置原型链
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

// 2. 设置构造函数间的原型链(class 特有)
Object.setPrototypeOf(Dog, Animal);
// Dog.__proto__ === Animal
// 这使得 Dog 可以访问 Animal 的静态方法

3.4 super 的本质

class Child extends Parent {
  constructor() {
    super(); // Parent.prototype.constructor.call(this)
  }

  method() {
    super.method(); // Parent.prototype.method.call(this)
  }

  static staticMethod() {
    super.staticMethod(); // Parent.staticMethod.call(this)
  }
}

super 在不同上下文中的行为:

上下文super 指向
constructor构造函数
实例方法Parent.prototype
静态方法Parent 本身

4. 原型链与 class 的陷阱

4.1 引用型共享

class List {
  items = []; // 实例属性,每个实例独立

  addItem(item) {
    this.items.push(item);
  }
}

// 如果写在 prototype 上会共享
function ListOld() {}
ListOld.prototype.items = []; //  所有实例共享同一个数组!

4.2 箭头函数this

class Button {
  constructor(label) {
    this.label = label;
  }

  // 箭头函数:this 绑定到实例
  handleClick = () => {
    console.log(this.label); // 正确
  };

  // 普通方法:this 取决于调用方式
  handleClickNormal() {
    console.log(this.label); // 可能丢失 this
  }
}

const btn = new Button('Submit');
const { handleClick, handleClickNormal } = btn;
handleClick(); // 'Submit'
handleClickNormal(); // undefined

4.3 多重继承限制

JavaScript 不支持多重继承,但可通过 Mixin 模式实现:

const Serializable = (Base) =>
  class extends Base {
    serialize() {
      return JSON.stringify(this);
    }
  };

const Loggable = (Base) =>
  class extends Base {
    log(message) {
      console.log(`[${this.constructor.name}] ${message}`);
    }
  };

class User extends Loggable(Serializable(Object)) {
  constructor(name) {
    super();
    this.name = name;
  }
}

const user = new User('Alice');
user.log('created'); // "[User] created"
user.serialize(); // '{"name":"Alice"}'