Class 新特性:类字段与私有字段
现代 class 支持公有/私有字段与静态块(取决于环境/编译)。
javascript
class Player {
#hp = 100; // 私有字段
name = "anon"; // 公有实例字段
static version = "1.0";
static {
console.log("Class loaded");
}
damage(n) {
this.#hp = Math.max(0, this.#hp - n);
}
get hp() {
return this.#hp;
}
}
const p = new Player();
p.damage(50);
console.log(p.hp); // 50
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
注意目标环境与编译配置(Babel/TypeScript)。
公有字段 vs 私有字段(#)
- 公有字段:直接定义在 class 内部的属性,实例可直接访问/修改。
- 私有字段:以
#name
声明,仅在类定义的内部可访问,外部访问会抛错。
javascript
class Enemy {
#state = "idle";
type = "slime";
setState(s) {
this.#state = s;
}
getState() {
return this.#state;
}
}
const e = new Enemy();
console.log(e.type); // 'slime'
console.log(e.getState()); // 'idle'
// e.#state; // SyntaxError:外部不可访问
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
访问器(getter/setter)与校验
javascript
class Chest {
#gold = 0;
get gold() {
return this.#gold;
}
set gold(n) {
if (!Number.isInteger(n) || n < 0) throw new TypeError("gold>=0");
this.#gold = n;
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
静态字段、静态方法与静态块
javascript
class Config {
static url = "/api";
static headers = { "X-App": "Arena" };
static get endpoint() {
return this.url + "/v1";
}
static {
console.log("Config class init");
}
}
console.log(Config.endpoint);
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
用途:一次性初始化、常量、工具方法。
初始化顺序与 this
类实例化时的执行顺序:
- 父类字段初始化;
- 父类构造函数;
- 子类字段初始化;
- 子类构造函数。
注意在子类构造函数中必须先 super()
后才能访问 this
。
方法中的 this
绑定选项
- 传统方法:在构造函数中手动绑定
javascript
class Button {
constructor() {
this.onClick = this.onClick.bind(this);
}
onClick(evt) {
/* 使用 this 安全 */
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- 类字段中使用箭头函数(词法 this)
javascript
class Button {
onClick = (evt) => {
/* this 为实例 */
};
}
1
2
3
4
5
2
3
4
5
权衡:箭头函数更简洁但每个实例持有一份函数;bind 也会为每个实例生成绑定函数,差别在可测试性与调试喜好。
与装饰器(Decorators)
JavaScript 装饰器已标准化(取决于目标环境与编译器支持)。可用于包装方法、字段元数据等。生态(Babel/TS)支持度较好,但用法需参考当前工具链版本。
常见陷阱
- 私有字段名字不能动态访问,也不能通过字符串索引:
obj['#x']
无效; - 私有字段在继承层级中是各自独立的,子类无法访问父类私有字段;
- 注意与旧版提案语法差异(一些资料可能过时);
- 大量使用类字段箭头函数可能影响内存占用(每实例一份),需权衡。
最佳实践
- 利用私有字段实现真正封装(替代过去的闭包或 WeakMap 私有化手段);
- 用访问器进行校验与封装不变量;
- 静态字段用于常量/配置,静态方法用于与实例无关的逻辑;
- 团队约定
this
绑定方式(bind vs 箭头函数),保持一致性。
练习
- 设计一个
BankAccount
类,使用#balance
私有字段、deposit/withdraw
方法包含校验与日志。 - 为某 UI 组件类添加点击处理:分别用构造器
bind
和类字段箭头函数实现,比较差异。 - 在一个
Config
类中用静态字段/访问器组织全局设置,并编写只读暴露接口。