JavaScript的class是函数和原型链的语法糖,本质为函数,不支持提升,constructor必须显式定义且仅一个,继承需调用super(),静态方法绑定类本身,实例方法绑定原型,不可用箭头函数。

JavaScript 用 class 关键字实现的不是传统意义上的类,而只是函数和原型链的语法糖——它不改变底层机制,但能让你写得更清晰、更少出错。
class 声明本质是函数,不是新类型
你写的 class Person 在运行时会被转成一个普通函数,并挂载到 Person.prototype 上。这意味着:
-
typeof Person返回"function",不是"class" - 不能用
new Person()之前就调用Person(),否则报TypeError: Class constructor Person cannot be invoked without 'new' - 类体中所有方法默认不可枚举(
Object.keys(Person.prototype)拿不到),但手动加的属性(如this.name = name)会出现在实例上
constructor 必须显式定义,且只能有一个
如果你没写 constructor,JS 会自动插入一个空的;但一旦写了,就不能再写第二个,否则报 SyntaxError: A class may only have one constructor。
常见误用:
立即学习“Java免费学习笔记(深入)”;
- 在
constructor里忘记调用super()(继承时),直接访问this会触发ReferenceError: Must call super constructor in derived class before accessing 'this' - 把异步操作(如
await fetch())直接塞进constructor——它不能是async,必须同步完成初始化
示例:
class User {
constructor(name) {
this.name = name;
}
}
class Admin extends User {
constructor(name, role) {
super(name); // 必须第一行
this.role = role;
}
}
静态方法、实例方法、getter/setter 的位置很关键
它们都写在 class 大括号内,但语义和绑定对象完全不同:
-
static init()→ 绑定在类本身:User.init(),不能通过实例调用 -
getName()(无static)→ 绑定在原型上:new User().getName() -
get id()→ 访问时像属性:user.id,但背后执行函数
注意:箭头函数不能用作类方法(包括 static),因为它没有自己的 this 绑定,且语法不允许出现在类体顶层(会报 Unexpected token)。
extends 和 instanceof 的行为依赖原型链,不是字符串匹配
class A extends B 实际做了两件事:设置 A.prototype.__proto__ === B.prototype,并让 A.__proto__ === B(静态继承)。所以:
-
new A() instanceof B是true,因为原型链向上能找到B.prototype - 但
Object.getPrototypeOf(A) !== B,而是A.__proto__ === B—— 这个细节影响工具库(比如Reflect.getPrototypeOf(A))的行为 - 如果父类是函数(非 class),
extends仍可工作,但子类constructor中的super()必须显式调用父函数,且不能省略括号
容易忽略的一点:class 声明不会被提升(hoisting),不像函数声明。下面代码会报 ReferenceError:
let u = new User(); // ❌
class User { }
真正难处理的不是语法,而是混用 class 和原型操作时的隐式耦合——比如在 class 外改 User.prototype.method = ...,或者用 Object.assign(User.prototype, {...}) 扩展方法,这些都能跑通,但会让代码意图模糊、难以调试。







