freeze、seal、preventExtensions对比
在Object常用的方法中,Object.freeze
和Object.seal
对于初学者而言,是两个较为容易混淆的概念,常常傻傻分不清两者的区别和应用场景
概念
先看看两者定义
Object.freeze
在MDN中的定义
Object.freeze()
方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze()
返回和传入的参数相同的对象。
Object.seal
在MDN中的定义
Object.seal()
方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要原来是可写的就可以改变。
从两者定义可以得到两者差异:Object.freeze
核心是冻结,强调的是不可修改。Object.seal
核心是封闭,强调的是不可配置,不影响老的属性值修改
差异
定义一个对象,接下来的对比围绕这个对象进行
"use strict";
const obj = {
name: "nordon"
};
使用Object.freeze
Object.freeze(obj);
Object.isFrozen(obj); // true
obj.name = "wy";
使用Object.isFrozen
可以检测数据是否被Object.freeze
冻结,返回一个Boolean
类型数据
此时对冻结之后的数据进行修改,控制台将会报错:Uncaught TypeError: Cannot assign to read only property 'name' of object '#<Object>'
使用Object.seal
Object.seal(obj);
Object.isSealed(obj); // true
obj.name = "wy";
使用Object.isSealed
可以检测数据是否被Object.seal
封闭,返回一个Boolean
类型数据
此时修改name
是成功的,此时的obj
也成功被修改
注意:若是不开启严格模式,浏览器会采用静默模式,不会在控制台抛出异常信息
共同点
主要以Object.seal
演示
不可删除
delete obj.name;
控制台将会抛出异常:Uncaught TypeError: Cannot delete property 'name' of #<Object>
不可配置
可以修改原有的属性值
Object.defineProperty(obj, 'name', {
value: 'wy'
})
不可增加新的属性值
Object.defineProperty(obj, "age", {
value: 12,
});
控制台将会抛出异常:Uncaught TypeError: Cannot define property age, object is not extensible
深层嵌套
两者对于深层嵌套的数据都表现为:无能为力
定义一个嵌套的对象
"use strict";
const obj = {
name: "nordon",
info: {
foo: 'bar'
}
};
对于obj
而言,无论是freeze
还是seal
,操作info
内部的数据都无法做到对应的处理
obj.info.msg = 'msg'
数据源obj
被修改,不受冻结或者冰封的影响
若是想要做到嵌套数据的处理,需要递归便利数据源处理,此操作需要注意:数据中包含循环引用时,将会触发无限循环
preventExtensions
最后介绍一下Object.preventExtensions
,为何这个方法没有放在与Object.freeze
、Object.seal
一起对比呢?因为其和seal
基本可保持一致,唯一的区别就是可以delete
属性,因此单独放在最后介绍
看一段代码
"use strict";
const obj = {
name: "nordon",
};
Object.preventExtensions(obj);
Object.isExtensible(obj); // false, 代表其不可扩展
delete obj.name;
作者:Nordon
链接:https://juejin.cn/post/7028389571561947172