在 JavaScript 中,可以通过 Object.freeze
API 将一个对象“冻结”起来。操作之后,对象就无法被修改,添加或删除属性。
如果需要判断一个对象是否被执行过 Object.freeze
操作,最简单的方法,就是使用 Object.isFrozen
API:
const obj = { key: 'value' };
const frozen = Object.freeze(obj);
console.log(Object.isFrozen(obj)); // => false;
console.log(Object.isFrozen(frozen)); // => true;
具体来说,Object.isFrozen
API 主要是针对对象做了以下几点判断:
- 对象是否是不可扩展的;
- 对象的所有属性是否都是不可配置的(
configurable = false
); - 对象的数据属性(没有 getter/setter 访问器属性)都是不可写的(
writable = false
)。
除了 Object.freeze
后的对象 isFrozen
一定为 true 外,根据上面的规则还可以构造出一些特殊的情况也返回 true:
const empty = { };
Object.preventExtensions(empty);
// 满足第一条;且因为没有其他属性,因此满足第二,第三条
console.log(Object.isFrozen(empty)); // => true
const obj = { key: 'value' };
// 满足第一条
Object.preventExtensions(obj);
// 满足第二条 & 第三条
Object.defineProperty(obj, 'key', { configurable: false, writable: false });
console.log(Object.isFrozen(obj)); // => true
const accessor = { get key() { return 'value' } };
// 满足第一条
Object.preventExtensions(accessor);
// 满足第二条
Object.defineProperty(accessor, 'key', { configurable: false });
// 因为没有数据属性,因此满足第三条
console.log(Object.isFrozen(accessor)); // => true
与 Object.freeze
类似,当 Object.isFrozen
API 传入值类型/null
/undefined
的时候,在 ES5 和 ES2015 环境下的行为略有不同:在 ES5 下,API 会直接报错(同 Object.freeze
);在 ES2015 中则会直接返回 true
。