isFrozen

JavaScript

在 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 主要是针对对象做了以下几点判断:

  1. 对象是否是不可扩展的;
  2. 对象的所有属性是否都是不可配置的(configurable = false);
  3. 对象的数据属性(没有 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