在 JavaScript 中保护对象 Protecting Objects in JavaScript
02 September 2013
这篇博客旨在快速复习如何在 JavaScript 中保护对象。有 3 种程度的保护:
- 最弱的是阻止扩展,
- 稍强的是封闭对象,
- 最强的是冻结对象。
1. 阻止扩展 ⬆
使对象不能再添加属性。例如
var obj = { foo: 'a' }; Object.preventExtensions(obj);
现在,在宽松模式下添加属性会静默失败:
> obj.bar = 'b'; > obj.bar undefined
而在严格模式[1]下会抛出一个错误,我们通过一个 IIFE[2] 使用严格模式。
> (function () { 'use strict'; obj.bar = 'b' }()); TypeError: Can't add property bar, object is not extensible
但是,仍然可以删除属性。
> delete obj.foo true > obj.foo undefined
1.1 检查对象是否可扩展 ⬆
检查 obj 是否可扩展:
> Object.isExtensible(obj) false
2. 封闭对象 ⬆
阻止扩展,并使所有属性“不可配置”。后者意味着属性的特性不可修改。只读的属性保持只读,可枚举的属性仍可枚举,等等。
(顺便说一句,因为历史原因,JavaScript 允许把不可配置的属性从可写改为只读。)
下面的例子演示了封闭使所有属性不可配置。
> var obj = { foo: 'a' }; > Object.getOwnPropertyDescriptor(obj, 'foo') // before sealing { value: 'a', writable: true, enumerable: true, configurable: true } > Object.seal(obj) > Object.getOwnPropertyDescriptor(obj, 'foo') // after sealing { value: 'a', writable: true, enumerable: true, configurable: false }
你仍然可以改变属性 foo:
> obj.foo = 'b'; 'b' > obj.foo 'b'
但是你不能改变它的特性:
> Object.defineProperty(obj, 'foo', { enumerable: false }); TypeError: Cannot redefine property: foo
Additionally, obj is not extensible, any more. 此外,obj 不再可扩展。
2.1 检查对象是否是封闭的 ⬆
检查 obj 是否是封闭的:
> Object.isSealed(obj) true
3. 冻结对象 ⬆
是所有属性不可写,并封闭对象。也就是说,对象不可扩展,所有属性为只读并不可修改。
var point = { x: 17, y: -5 }; Object.freeze(point);
在宽松模式中,将再次静默失败:
> point.x = 2; // no effect, point.x is read-only > point.x 17 > point.z = 123; // no effect, point is not extensible > point { x: 17, y: -5 }
在严格模式中则抛出一个错误:
> (function () { 'use strict'; point.x = 2 }()); TypeError: Cannot assign to read-only property 'x' > (function () { 'use strict'; point.z = 123 }()); TypeError: Can't add property z, object is not extensible
3.1 检查对象是否是冻结的 ⬆
检查 obj 是否是冻结的:
> Object.isFrozen(point) true
4. 参考文献 ⬆
- JavaScript’s strict mode: a summary
- JavaScript variable scoping and its pitfalls
- Object properties in JavaScript