从语法糖到引擎实现——JavaScript Class 完整指南(2025 版)

67 阅读4分钟

☕ 404 星球 · 前端晨间广播 | 2025-10-26

1️⃣ Gemini 3.0 全家桶凌晨发布
Google 正式推出 Gemini 3.0 Pro/Flash/Ultra,MoE 架构、万亿参数;配套 Gemini-CLI 可一键生成 React + TypeScript 项目骨架,官方称“原型到生产 5 分钟”,前端脚手架迎来“大模型原生”时代。

2️⃣ 川渝 Web 前端开发技术交流会今日开幕
重庆两江软件园现场议题:AI 低代码、鸿蒙原生开发、性能监控实战;设有“AI 应用创作大赛”与招聘专区,线上同步直播,免费报名即领周边。

3️⃣ Figma 正式收购 Payload CMS
设计到内容一站式工作流首次闭环:设计师在 Figma 即可调用 Payload GraphQL 端点,自动生成 TypeScript 类型安全的组件代码,开源承诺保持不变,插件市场预计 11 月上线 Beta。

4️⃣ CSS @scope 全平台通关
Firefox 132 Nightly 默认开启 @scope,至此 Chrome、Safari、Firefox 三大内核全部支持,组件级样式隔离无需 CSS Modules,2026 进候选标准。

5️⃣ Node.js 安全补丁紧急推送
10 月安全版本同时修复 2 个 HIGH 级漏洞(HTTP 走私 + DNS 重绑定),23.x、22.x、20.x LTS 同步获得更新,官方建议生产环境 24h 内升级。

— ☕️🌅 —

一、写在前面:为什么又要讲 Class?

ES6 发布已近十年,「Class 只是语法糖」这句话几乎成了面试口头禅。
但 2022 之后,ECMAScript 一口气塞进了「私有字段、静态初始化块、装饰器」三把大杀器,很多老教程明显过时。
今天这篇,就带你从「写代码」到「看引擎」,一次性把 Class 吃干抹净。


二、十分钟速通:Class 语法全景图

1. 最简洁的类

class Person {
  name = 'Anonymous';          // 实例字段
  #age = 0;                    // 私有字段(ES2022)

  constructor(name) {
    this.name = name;
  }

  greet() {                    // 实例方法
    console.log(`Hi, ${this.name}, age ${this.#age}`);
  }

  static species = 'Homo sapiens';
  static create(name) {        // 静态方法
    return new this(name);
  }

  static {                     // 静态初始化块(ES2022)
    console.log('Person class loaded');
  }
}

2. 继承一条链

class Employee extends Person {
  #salary;

  constructor(name, salary) {
    super(name);               // 必须在 this 之前
    this.#salary = salary;
  }

  greet() {
    super.greet();             // 调用父类实例方法
    console.log('And I am an employee');
  }

  static createIntern(name) {
    return super.create(name); // 调用父类静态方法
  }
}

3. 使用侧代码

const e = Employee.createIntern('Alex');
e.greet();
// 控制台:
// Person class loaded
// Hi, Alex, age 0
// And I am an employee

三、灵魂追问:Class 到底生成了什么?

1. 类 = 函数 + 原型

typeof Person // "function"
Person.prototype.constructor === Person // true

2. 继承 = 两条链

// 静态链
Employee.__proto__ === Person // true

// 实例链
Object.getPrototypeOf(Employee.prototype) === Person.prototype // true

3. 私有字段的魔法

引擎在每次实例化时创建一个隐藏的 WeakMap,用「brand check」保证外部无法访问:

const p = new Person('Tom');
p.#age // SyntaxError: Private field '#age' must be declared in an enclosing class

四、实战踩坑合集

坑点示例正确姿势
提升new Foo(); class Foo{}ReferenceError,类不会提升
super 顺序thissuper必报错
this 丢失const {greet} = employee; greet()用箭头函数或 bind
私有字段被反射Reflect.ownKeys(obj)列表里永远找不到 #xxx
静态块异步static { await fetch() }语法错误,静态块内部不能直接用 await(可用 IIFE)

五、进阶玩法:装饰器 + Mixin + 高阶类

1. 装饰器(Stage-3)

@frozen
class API {
  @throttle(300)
  call() {}
}

function frozen(Constructor) {
  Object.freeze(Constructor);
  Object.freeze(Constructor.prototype);
}

2. Mixin:组装更小的类

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

class Model extends Serializable(Person) {}

3. 高阶类(HOC)

function withLog(Cls) {
  return class extends Cls {
    constructor(...a) {
      super(...a);
      console.log('New', Cls.name, this);
    }
  };
}
const Logged = withLog(Employee);

六、性能与内存小贴士

  1. 实例字段箭头函数
    foo = () => {} 每个实例一份闭包,方便但占内存;高并发场景慎用。
  2. 方法放原型
    foo() {} 全部实例共享,内存友好。
  3. 私有字段成本
    引擎会分配额外存储空间,对百万级对象才有感觉,普通业务可忽略。

七、一张图总结(保存即可)

-------------------------┐
│        类声明            │
│  constructor            │
│  实例方法 / 字段         │
│  私有方法 / 字段 (#)     │
│  静态方法 / 字段 (static)│
│  静态初始化块 (static{}) │
└------------┬------------┘
             │ extends
             ▼
┌-------------------------┐
│  子类 (两条链)          │
│  静态链:Child→Parent    │
│  原型链:Child.prototype│
│          →Parent.prototype│
└-------------------------┘

八、写在最后

Class 语法让 JavaScript 看起来更像“正统 OO”,但骨子里依旧是原型。
理解「prototype、super、静态链、私有字段」这四块基石,你就能在「写业务」和「读源码」之间游刃有余。
如果本文对你有帮助,点个 ,我们评论区见!