类字段是ES2022定义的公共实例属性,实例化时通过Object.defineProperty添加到实例;对象字面量是运行时立即求值创建的独立对象。二者语法相似但机制不同:类字段不可动态键名、具默认描述符且不可配置性受限,对象字面量更灵活但无继承上下文。

类定义中的属性声明和对象字面量看似都在“写属性”,但底层机制、执行时机和行为表现有本质区别。
语法形式相似,但本质不同
类中直接写的字段(如 name = 'Alice')是公共类字段(public class fields),属于 ES2022 正式特性;而对象字面量(如 { name: 'Alice' })是运行时创建的对象实例。前者在类定义阶段就参与构造逻辑,后者是值表达式,立即求值生成对象。
- 类字段不是“赋值语句”,而是属性定义——它会触发
Object.defineProperty级别的描述符设置(默认writable: true, enumerable: true, configurable: true) - 对象字面量的键值对也是定义行为,但发生在对象创建那一刻,不涉及类的原型链或初始化流程
- 两者都支持计算属性名(
[key]: value),但类字段不支持动态键名(不能用[expr]写在类体顶层)
执行时机与作用域位置不同
类字段在实例化时(即 new MyClass() 执行过程中)才被添加到新对象上;而对象字面量一求值就生成完整对象,无需实例化过程。
- 类字段会被挂载到每个实例上,不是原型属性,也不共享
- 对象字面量每次执行都新建一个独立对象,不存在“复用”或“继承”概念
- 类字段可访问
this上下文(比如依赖其他字段或方法),对象字面量内部无法直接引用自身(除非用函数或 getter)
可枚举性与继承行为一致,但不可配置性有差异
两者默认都是可枚举、可写、可配置的,但类字段一旦定义,其描述符在实例上不可被 Object.defineProperty 修改为 configurable: false(除非显式设置);而对象字面量属性可通过 defineProperty 自由调整。
-
for...in和Object.keys()都能遍历二者声明的属性(前提是未设enumerable: false) - 类字段不会出现在原型上,只属于实例;对象字面量属性也只属于该对象本身
- 若在类中用
Object.defineProperty(this, 'x', {...})显式定义,则可绕过默认行为,获得更精细控制
实际编码中容易混淆的点
很多人把类字段当成“简化的赋值”,但其实它不等价于构造函数里 this.name = 'Alice' 的赋值操作——后者是运行时赋值,前者是定义行为,会影响属性的元数据(如是否可删除、是否出现在 JSON.stringify 中)。
- 类字段支持初始化表达式(
count = this.items?.length || 0),但不能访问尚未声明的字段(存在暂时性死区) - 对象字面量支持嵌套结构、函数、甚至其他对象,灵活性更高;类字段更适合扁平、声明式的实例状态建模
- TypeScript 中类字段还能带类型注解(
name: string = 'Alice'),对象字面量需靠类型断言或接口约束

















