应直接在原型对象(如MyClass.prototype)上调用Object.defineProperties批量定义高精度属性描述符,需明确指定完整descriptor结构(含value/get、writable、enumerable、configurable),避免作用于实例或混合value与get/set,注意不可扩展性及原生原型修改风险。

直接用 Object.defineProperties 为原型对象批量定义高精度属性描述符,关键在于明确目标对象、属性名与完整 descriptor 结构,并确保操作的是原型而非实例。
明确操作目标:必须作用于原型对象
若想让所有实例共享这些高精度属性(如只读、不可枚举、不可配置),需将属性定义在构造函数的 prototype 上,而非实例本身。错误做法是传入实例或空对象;正确做法是传入 MyClass.prototype 或 Object.getPrototypeOf(instance)。
- ✅ 正确:
Object.defineProperties(MyClass.prototype, descriptors) - ❌ 错误:
Object.defineProperties(new MyClass(), descriptors)(仅影响单个实例) - ⚠️ 注意:若使用 class 语法,
MyClass.prototype是可写的,但不能覆盖整个 prototype,只能增补
构造 descriptor 对象:每个属性需完整声明特性
高精密意味着显式控制 value/get、writable、enumerable、configurable。不能省略字段——未声明的特性会取默认值(如 value 默认 undefined,writable 默认 false 当含 get/set 时)。
- 定义只读常量:
{ value: 42, writable: false, enumerable: true, configurable: false } - 定义 getter 属性:
{ get() { return this._x * 2; }, enumerable: true, configurable: true }(注意:含get时value和writable会被忽略) - 避免混合使用:
value和get不能共存;否则 descriptor 无效且静默失败
一次注入多个属性:descriptor 参数是键值对对象
Object.defineProperties 的第二个参数是一个对象,其每个键是属性名,对应值是 descriptor。可安全一次性注入任意数量属性,无需循环调用 defineProperty。
- 示例:
Object.defineProperties(Date.prototype, { isLeapYear: { get() { const y = this.getFullYear(); return (y % 4 === 0 && y % 100 !== 0) || y % 400 === 0; }, enumerable: false, configurable: true }, dayOfYear: { get() { const start = new Date(this.getFullYear(), 0, 0); return Math.floor((this - start) / 1000 / 60 / 60 / 24); }, enumerable: false, configurable: true } });
兼容性与限制:注意不可扩展与已有属性冲突
若原型已被设为不可扩展(Object.preventExtensions()),或某属性已存在且 configurable: false,则对应 descriptor 中的 configurable: true 或新增属性会抛错。
- 建议提前检查:
Object.isExtensible(obj)和Object.getOwnPropertyDescriptor(obj, key) - 若需强覆盖,先用
delete obj[key](仅当configurable: true时有效) - 不推荐在原生原型(如
Array.prototype)上随意添加,可能引发冲突或性能问题
只要 descriptor 结构准确、目标明确、避开不可配置/不可扩展限制,一次性注入高精度属性描述并不复杂,但容易因默认值误解或目标错位导致失效。

















