Object.defineProperties
详解
Object.defineProperties
是 JavaScript 中用于在一个对象上定义或修改多个属性的方法。它是 Object.defineProperty
的复数版本,允许你一次性定义多个属性。
基本语法
Object.defineProperties(obj, props)
obj
:要在其上定义或修改属性的对象props
:一个对象,其键表示要定义或修改的属性名,值是对应属性的描述符对象
属性描述符
每个属性描述符可以包含以下可选键:
数据描述符
value
:属性的值(默认为undefined
)writable
:是否可写(默认为false
)enumerable
:是否可枚举(默认为false
)configurable
:是否可配置(默认为false
)
存取描述符
get
:作为该属性的 getter 函数(默认为undefined
)set
:作为该属性的 setter 函数(默认为undefined
)
注意:数据描述符和存取描述符不能同时使用(即不能既有 value
又有 get
)
使用示例
1. 定义多个数据属性
const obj = {};Object.defineProperties(obj, {property1: {value: true,writable: true},property2: {value: 'Hello',writable: false}
});console.log(obj.property1); // true
console.log(obj.property2); // 'Hello'
2. 定义存取器属性
const person = {};
let ageValue = 0;Object.defineProperties(person, {name: {value: 'John',writable: true},age: {get: function() {return ageValue;},set: function(newValue) {if (newValue >= 0) {ageValue = newValue;}},enumerable: true}
});person.age = 30;
console.log(person.age); // 30
person.age = -5; // 不会设置,因为值无效
console.log(person.age); // 仍然 30
3. 控制属性特性
const car = {};Object.defineProperties(car, {brand: {value: 'Toyota',writable: false, // 不可写enumerable: true, // 可枚举configurable: false // 不可配置},model: {value: 'Camry',writable: true,enumerable: false, // 不可枚举configurable: true}
});console.log(Object.keys(car)); // ['brand'] - model不可枚举
car.brand = 'Honda'; // 静默失败(严格模式下会报错)
console.log(car.brand); // 'Toyota'
与 Object.defineProperty
的区别
特性 | Object.defineProperty | Object.defineProperties |
---|---|---|
一次性能定义的属性数 | 1个 | 多个 |
性能 | 略快 | 略慢(但批量操作更高效) |
使用场景 | 单个属性操作 | 多个属性批量操作 |
实际应用场景
1. 创建不可变对象
const constants = {};Object.defineProperties(constants, {PI: {value: 3.14159,writable: false,enumerable: true,configurable: false},E: {value: 2.71828,writable: false,enumerable: true,configurable: false}
});
2. 实现私有变量
function Person(name) {let _age = 0;Object.defineProperties(this, {name: {value: name,writable: true},age: {get: function() { return _age; },set: function(value) {if (value >= 0) _age = value;},enumerable: true}});
}const p = new Person('Alice');
p.age = 30;
console.log(p.age); // 30
p.age = -5; // 无效
console.log(p.age); // 仍然 30
3. 扩展对象功能
// 安全地扩展原型(避免枚举)
Object.defineProperties(Array.prototype, {sum: {value: function() {return this.reduce((a, b) => a + b, 0);},enumerable: false},average: {value: function() {return this.length ? this.sum() / this.length : 0;},enumerable: false}
});const nums = [1, 2, 3];
console.log(nums.sum()); // 6
console.log(nums.average()); // 2
注意事项
- 默认值:如果不指定,
writable
,enumerable
和configurable
默认为false
- 严格模式:在严格模式下,违反属性描述符限制会抛出错误
- 性能:频繁使用会影响性能,适合初始化时使用
- 兼容性:ES5 特性,但现代浏览器和Node.js都支持
Object.defineProperties
提供了对对象属性更精细的控制能力,特别适合需要精确控制属性行为的场景。