JavaScript中,我们希望别人无法修改我们创建的对象。比如,代码库的作者很可能想锁定核心库的某些部分来保证它们不被意外地修改。ES5中引入了三种锁定修改的级别:防止扩展preventExtensions、密封seal、冻结frezze。
这三种级别逐渐增强。对于超过级别的行为,在非严格模式下将会悄无声息地失败,在严格模式下将会抛出一个错误。因此,建议使用严格模式,更加方便调试。
正常对象:
可以添加属性和方法,所有属性和方法可以被删除、修改。
var person = {
name: "Nicholas"
};
1. Object.preventExtensions(阻止扩展)
禁止为对象添加属性和方法。但已存在的属性和方法可以被修改或删除。
实施操作:Object.preventExtensions()
检测是否应用该操作:Object.isExtensible()
Object.preventExtensions(person);
console.log(Object.isExtensible(person)); // false
person.age = 25; // 防止扩展
console.log(person.age); // undefined
2. Object.seal(密封)
禁止为对象删除已存在的属性和方法。被密封的对象也是不可扩展的。
实施操作:Object.seal()
检测是否应用该操作:Object.isSealed()
Object.seal(person);
console.log(Object.isExtensible(person)); // false
console.log(Object.isSealed(person)); // true
person.age = 25; // 防止扩展
console.log(person.age); // undefined
delete person.name; // 防止删除
console.log(person.name); // Nicholas
3. Object.freeze(冻结)
禁止为对象修改已存在的属性和方法。所有字段均只读。被冻结的对象也是不可扩展和密封的。
实施操作:Object.freeze()
检测是否应用该操作:Object.isFrozen()
Object.freeze(person);
console.log(Object.isExtensible(person)); // false
console.log(Object.isSealed(person)); // true
console.log(Object.isFrozen(person)); // true
person.age = 25; // 防止扩展
console.log(person.age); // undefined
delete person.name; // 防止删除
console.log(person.name); // Nicholas
person.name = "Greg" // 防止修改
console.log(person.name); // Nicholas
注意:
- 对于同一个对象,防止扩展-->密封-->冻结这种操作是不可逆的。一旦该对象被冻结,是无法恢复到防止扩展或密封状态的。一旦该对象被密封,是无法恢复到防止扩展状态的。一旦对象被锁定,它将无法解锁。
Object.freeze(person);
person.name = "Greg"; // 防止修改
console.log(person.name); // Nicholas
Object.preventExtensions(person); // 无法回退
person.name = "Greg"; // 防止修改
console.log(person.name); // Nicholas
- Object.seal()方法,会在一个现有对象上调用Object.preventExtensions(),并把所有属性标记为configurable: false。
- Object.freeze()方法,会在一个现有对象上调用Object.seal(),并把所有属性标记为writable: false。
- 深度冻结一个对象是指,首先在这个对象上调用Object.freeze(),然后遍历它引用的所有对象,并且在这些对象上调用Object.freeze()。