You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JS转TS重构时,直接赋值属性与仅设value的Object.defineProperties有差异吗?

两种写法运行逻辑存在明确差异,核心来自Object.defineProperties的属性描述符默认值规则

JS里使用Object.defineProperties/Object.defineProperty定义属性时,未显式声明的描述符项默认值都为false,而直接通过this.title = title赋值创建的属性,三个核心描述符默认值都为true,具体差异体现在三个方面:

  • 可写性(writable):第一种写法的title属性运行时不可被重新赋值,非严格模式下赋值操作会静默失败,严格模式下直接抛出TypeError;第二种写法的title可随意修改
  • 可枚举性(enumerable):第一种写法的title不会被Object.keys()、for...in遍历、JSON.stringify()等枚举操作识别返回;第二种写法的title属于可枚举属性,会参与所有枚举逻辑
  • 可配置性(configurable):第一种写法的title无法被delete操作删除,也无法再次通过Object.defineProperties修改它的描述符配置;第二种写法的title可被删除,也可后续调整描述符

你可以用以下代码验证差异:

// 第一种写法实例表现
const foo1 = new Foo({ name: "测试1", title: "标题1" });
foo1.title = "新标题1";
console.log(foo1.title); // 输出:标题1(赋值无效)
console.log(Object.keys(foo1)); // 输出:['name'](title不可枚举)
console.log(delete foo1.title); // 输出:false(删除失败)

// 第二种写法实例表现
const foo2 = new Foo({ name: "测试2", title: "标题2" });
foo2.title = "新标题2";
console.log(foo2.title); // 输出:新标题2(赋值有效)
console.log(Object.keys(foo2)); // 输出:['name', 'title'](title可枚举)
console.log(delete foo2.title); // 输出:true(删除成功)

迁移建议

如果原有代码的业务逻辑就是希望title属性不可修改、不可枚举、不可删除,直接改为第二种写法会引发业务故障。如果是当初写第一种写法的开发者不了解默认规则,本来就是要普通属性的行为,那可以放心改第二种写法,或者保留第一种写法的话补充描述符配置即可:

Object.defineProperties(this, {
  title: { 
    value: title,
    writable: true,
    enumerable: true,
    configurable: true
  }
})

如果是迁移到TypeScript的场景要注意:TS的readonly修饰符仅做编译阶段的赋值校验,不会影响运行时的可写性,如果需要运行时真正不可修改的属性,还是需要保留Object.defineProperties写法。

内容的提问来源于stack exchange,提问作者Fogmeister

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 12:57:02