js-class
class 是原型机制的现代语法层。
#type / concept
#status / growing
#resource / javascript
#resource / ecmascript
[!info] related notes
- 所属 MOC: ecmascript-object-oriented, ecmascript-prototypes, ES6 新特性 MOC
- 前置概念: js构造函数, js-new
- 并列概念: js继承in-es6-es5
- 易混淆概念: 为什么说-js-是基于原型而不是基于类
- 关系笔记: ecmascript-object-oriented, ecmascript-prototypes
js-class
一句话定义
class 是 ES6 引入的语法糖,让基于原型的继承写起来更像传统面向类语言,但底层仍然是原型链。
核心机制 / 工作原理
class声明在底层生成一个构造函数,class本体中的方法定义在构造函数的prototype对象上。constructor是特殊的默认方法,new调用时执行;不写则自动生成空的。extends设置原型链:子类的[[Prototype]]指向父类,子类.prototype的[[Prototype]]指向父类.prototype。super()在子类constructor中必须先调用,它调用父类构造函数并绑定this。static方法/字段定义在类本身(构造函数)上,不在.prototype上,子类可继承。#前缀声明私有字段/方法,外部无法访问,是真正的运行时私有。
最小代码示例
// 基本 class
class Animal {
#name; // 私有字段
constructor(name) {
this.#name = name;
}
speak() {
return `${this.#name} makes a sound`;
}
static create(name) {
return new Animal(name);
}
}
// 继承
class Dog extends Animal {
constructor(name) {
super(name); // 必须在使用 this 之前调用
}
speak() {
return super.speak() + ' - Woof!';
}
}
const dog = new Dog('Rex');
dog.speak(); // "Rex makes a sound - Woof!"
// 原型等价证明
class Foo {
bar() { return 42; }
}
// 等价于:
function Foo2() {}
Foo2.prototype.bar = function() { return 42; };
console.log(Foo.prototype.bar); // [Function: bar]
console.log(typeof Foo); // "function" — class 底层就是函数
class 表达式
const MyClass = class MyClassInner {
// MyClassInner 只在类内部可用,外部用 MyClass
identify() {
return MyClassInner.name; // ok
}
};
边界与常见误解
- class 不是新的对象模型:它只是
prototype的语法糖,typeof class {}仍然是"function"。 - class 默认严格模式:class 体内的代码自动处于严格模式,不会意外创建全局变量。
- 不存在类提升:虽然 class 声明在语法上会提升,但与
let/const一样存在暂时性死区(TDZ),在声明前访问会报ReferenceError。 - 私有字段
#不是约定:不像_前缀只是社区约定,#是语言级强制私有,外部访问直接SyntaxError或TypeError。 - 何时用 class vs 工厂函数:需要
new/instanceof/原型继承链时用 class;需要更灵活的闭包封装、不需要继承体系时,工厂函数更简洁。