在 JavaScript 中保护对象 Protecting Objects in JavaScript
02 September 2013
这篇博客旨在快速复习如何在 JavaScript 中保护对象。有 3 种程度的保护:
- 最弱的是阻止扩展,
- 稍强的是封闭对象,
- 最强的是冻结对象。
阻止扩展
使对象不能再添加属性。例如
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
检查对象是否可扩展
检查 obj 是否可扩展:
> Object.isExtensible(obj)
false
封闭对象
阻止扩展,并使所有属性“不可配置”。后者意味着属性的特性不可修改。只读的属性保持只读,可枚举的属性仍可枚举,等等。
(顺便说一句,因为历史原因,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 不再可扩展。
检查对象是否是封闭的
检查 obj 是否是封闭的:
> Object.isSealed(obj)
true
冻结对象
是所有属性不可写,并封闭对象。也就是说,对象不可扩展,所有属性为只读并不可修改。
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
检查对象是否是冻结的
检查 obj 是否是冻结的:
> Object.isFrozen(point)
true
参考文献
- JavaScript’s strict mode: a summary
- JavaScript variable scoping and its pitfalls
- Object properties in JavaScript
blog comments powered by Disqus