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
提供了對對象屬性更精細的控制能力,特別適合需要精確控制屬性行為的場景。