Get to know MDN better
此页面由社区从英文翻译而来。了解更多并加入 MDN Web Docs 社区。
Object.freeze() 静态方法可以使一个对象被冻结。冻结对象可以防止扩展,并使现有的属性不可写入和不可配置。被冻结的对象不能再被更改:不能添加新的属性,不能移除现有的属性,不能更改它们的可枚举性、可配置性、可写性或值,对象的原型也不能被重新指定。freeze() 返回与传入的对象相同的对象。
冻结一个对象是 JavaScript 提供的最高完整性级别保护措施。
要冻结的对象。
传递给函数的对象。
冻结一个对象相当于阻止其扩展然后将所有现有属性的描述符的 configurable 特性更改为 false——对于数据属性,将同时把 writable 特性更改为 false。无法向被冻结的对象的属性中添加或删除任何内容。任何这样的尝试都将失败,可能是静默失败,也可能抛出一个 TypeError 异常(通常情况下,在严格模式中抛出)。
对于被冻结对象的数据属性,它们的值不能被更改,因为它们的 writable 和 configurable 特性被设置为 false。访问器属性(getter 和 setter)也相同——getter 返回的属性值仍然可以更改,setter 可以在设置属性时调用而不抛出错误。请注意,对象类型的值仍然可以修改,除非它们也被冻结。数组作为一种对象也可以被冻结;数组被冻结后,既不能更改它的元素,也不能向数组中添加或删除元素。
freeze() 返回传递给函数的同一对象。它不会创建一个被冻结的副本。
尝试冻结带有元素的 TypedArray 或 DataView 会导致 TypeError,因为它们是内存视图,可能会引起其他问题:
请注意,由于标准中的三个属性(buf.byteLength、buf.byteOffset 和 buf.buffer)是只读的(就像 ArrayBuffer 或 SharedArrayBuffer 的属性一样),因此没有理由尝试冻结这些属性。
与 Object.seal() 不同,使用 Object.freeze() 冻结的对象中的现有属性是不可变的,数据属性不能被重新赋值。
被冻结的对象是不可变的。但也不总是这样。以下示例显示被冻结的对象不是常量(浅冻结)。
对于一个常量对象,整个引用图(直接和间接引用其他对象)只能引用不可变的冻结对象。冻结的对象被认为是不可变的,因为整个对象中的整个对象状态(对其他对象的值和引用)是固定的。注意,字符串、数字和布尔值总是不可变的,而函数和数组是对象。
调用 Object.freeze(object) 的结果仅适用于 object 本身的直接属性,并且只会在 object 上防止未来的属性添加、删除,或重新赋值的操作。如果这些属性的值本身是对象,这些对象不会被冻结,并且可能成为属性添加、删除,或重新赋值操作的目标。
为了使对象不可变,需要递归地冻结每个对象类型的属性(深冻结)。当且仅当你知道对象在引用图中不包含循环引用时,可以根据你的设计逐个案例地使用该模式,否则会导致无限循环。deepFreeze() 的一个增强功能是添加一个内部函数,该函数接收一个路径(例如一个数组)参数,这样可以在调用 deepFreeze() 递归地冻结对象时,避免冻结正在被处理的对象。但仍有可能会冻结不应该被冻结的对象,例如 window。
| ECMAScript® 2027 Language Specification # sec-object.freeze |
启用 JavaScript 以查看此浏览器兼容性表。