ES6新语法Object.freeze和Object.seal基本使用
作者:前端兰博 时间:2024-04-10 16:10:04
引言
随着ES6新语法的不断迭代更新,已经出现了许多常用的工具api。今天我将为大家推荐两款明星api,它们就是Object.freeze和Object.seal。究竟它两可以带给我们怎样的惊喜?我只能用两个字形容:NB
Object.freeze
1.基本使用
首先从单词含义分析 freeze代表冰冻,嗯那这个api就是冰冻/冻结对象的意思。接着我们看看mdn的解释吧
MDN官方解释
Object.freeze()
方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。
官方就是踏马官方啊,解释的我都怀疑自己没学过语文,绕来绕去。其实它就说了一句话,Object.freeze可以让一个对象无法增加新属性,无法删除已有属性,无法修改已有属性。本质就是指目标对象只能读,其它任何操作都无效。
功能演示
通过Object.freeze处理的对象,进行删除,添加,修改都是无效的,并且在非严格模式下是不会报错的。
let obj = {name:"dzp",age:22}
Object.freeze(obj)
obj.name = "dzp2"//修改无效
delete obj.age//删除无效
obj.a = 1//添加无效
console.log(obj)// {name:"dzp",age:22}
拓展
看到上面的操作,部分童鞋可能疑问这个对数组可以冻结?数组在js里面也属于对象,所以数组也是可以冻结的。冻结后的数组也是只读的
let arr = [1]
Object.freeze(arr)
arr[0] = 2//无效
arr.push(2)//无效
arr.shift()//无效
console.log(arr)//[1]
2.Object.freeze与const对比
看到freeze大家肯定会联想到另一个api,它就是const。它们感觉都有冻结的意思,其实二者设计初衷和功能点还是相差甚远。
const通常我们用它修饰普通变量,用const定义的普通变量值无法修改。而const定义的对象地址无法修改,其内部的属性仍然是可变的。
const定义普通变量
const a = 10
a = 20//error,报错无法修改
const定义对象
const obj = {a:1}
obj.a = 2//ok
obj = {}//error,报错,不能修改地址
二者对比总结
const通常定义普通变量,而Object.freeze通常定义对象
const定义普通变量时,值无法修改。定义对象时,地址无法修改,但是对象内部属性可以任意改变。
Object.freeze修饰的对象只能读,其它任何操作都是无效的。
Object.freeze修饰的对象可以改变地址,改变地址后的对象就失去了freeze控制了,当然这个操作是毫无意义的。
3.常用功能
下面简单列举下Object.freeze的常用小功能吧。
冻结目标对象(默认是浅冻结)
vue2中数据的性能优化
功能一:冻结目标对象
看到这,估计有人要喷了。冻结对象不是很明显的?还要介绍一遍?大哥,大姐们稍安勿躁。容我慢慢狡辩。
Object.freeze冻结对象是浅度冻结,并非深度冻结。通常我们希望一个对象数据是完全只读的。而单纯的使用Object.freeze是无法实现对象完全可读。
浅冻结示例
let obj = {name:"dzp",a:{b:1}}
Object.freeze(obj)
obj.name = "dzp2"//无法修改
obj.a.b = 2//可以修改
console.log(obj)//{name:"dzp",a:{b:2}}
看到上面的结果大家就很容易发现,freeze对对象的冻结只能作用到第一层上,当对象层级大于等于2时,后面的冻结就失效了。这其实就是浅冻结,浅冻结和浅比较可以理解成一类,其中React函数组件通常我们会使用memo进行优化,此处的设计就是利用浅比较完成的。
深度冻结对象
上面我们知道了用freeze只能对对象进行浅度冻结,无法真正冻结一个多层嵌套对象的对象。通常我们需要自己设计深冻结。如下例子内部出现了Object.seal。大家不必着急,可以先看完后面Object.seal的介绍,然后再继续看深冻结例子。(Object.seal后面讲更清晰)
功能二:vue2数据优化
Object.freeze是如何对vue2的数据做到优化?我们清楚vue2的data数据都是具备响应式的,数据通过defineProperty完成响应式设置,但是这本身耗费了一定性能。如果我们有接口数据仅仅做展示并且数目较多。那么对其进行响应式监听无疑是没必要的。但是vue2渲染界面的数据都是响应式的,如何消除数据的响应式?Object.freeze就可以做到消除响应式。
<template>
<div id="app">
<div v-for="item in list" :key=item>{{item}}</div>
<div @click="changeData()">修改数据</div>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
list:[]
}
},
mounted(){
//模拟接口获取数据
setTimeout(() => {
this.list.push(...[1,2,3,4,5])
//将数据取消响应式
Object.freeze(this.list)
}, 2000);
},
methods:{
changeData () {
this.list.push(6)
}
}
}
</script>
效果
如果是未添加Object.freeze的数组,此处肯定是正常显示6个,但是通过freeze我们直接消除了数据的响应式,让这个数据只能展示而无法修改,同时也一定程度提升了性能。
Object.seal
Object.seal其实没有Object.freeze使用的频繁,但是一些工具还是需要它的配合,例如使用Object.seal可以模拟Object.freeze的浅度和深度的对象监听。
1.基本使用
MDN介绍
Object.seal()
方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要原来是可写的就可以改变。
还是简单总结官方的话语:Object.seal修饰的对象无法添加或者删除属性,可以修改可以读取。
简单使用
let obj = {name:"dzp"}
Object.seal(obj)
obj.age = 22//无法添加
obj.name = "dzp2"//可以修改
delete obj.name//无法删除
console.log(obj)//{name:"dzp2"}
值得注意的是Object.freeze和Object.seal都是对对象浅控制,只作用于第一层。大于等于2层级的对象不受控制。
let obj = {name:'dzp',a:{b:1}}
delete obj.a.b
console.log(obj)//{ name: 'dzp', a: {} }
2.模拟Object.freeze
模拟Object.freeze是一道经典的面试手撕代码题,我们可以借助Object.seal轻松的完成设计。整体设计还是比较简单,使用seal控制对象不可以增加和删除属性。然后使用Object.defineProperty让对象无法修改属性
function myFreeze(obj) {
if(obj instanceof Object) {
Object.seal(obj)
for(let key in obj) {
Object.defineProperty(obj,key,{
writable:false
})
}
}
}
let obj = {name:"dzp",a:{b:1}}
myFreeze(obj)
obj.name = "dzp2"//无效
delete obj.name//无效
obj.age = 22//无效
obj.a.b = 2//有效,只冻结第一层
console.log(obj)//{name:"dzp",a:{b:2}}
3.模拟Object.freeze,同时保证对象深冻结
深度冻结在浅度冻结的基础上,只需要加一个递归就可以实现,整体设计十分清晰简单。
function myFreeze(obj) {
if(obj instanceof Object) {
Object.seal(obj)
for(let key in obj) {
Object.defineProperty(obj,key,{
writable:false
})
myFreeze(obj[key])
}
}
}
let obj = {name:"dzp",a:{b:1}}
myFreeze(obj)
obj.name = "dzp2"//无效
delete obj.name//无效
obj.age = 22//无效
obj.a.b = 2//无效,深冻结了
console.log(obj)//{name:"dzp",a:{b:2}}
来源:https://juejin.cn/post/7155143704771526670
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
python optparse模块使用实例
Mootools 1.2教程(19)——Tooltips
python绘制浅色范围曲线的示例代码
![](https://img.aspxhome.com/file/2023/0/127020_0s.png)
Python模块/包/库安装的六种方法及区别
![](https://img.aspxhome.com/file/2023/4/72964_0s.png)
vue实现动态路由详细
使用线框图来简化你的产品设计流程
python argparser的具体使用
Python matplotlib实时画图案例
![](https://img.aspxhome.com/file/2023/1/124111_0s.gif)
Git的基础文件操作初始化查看添加提交示例教程
numpy数组之存取文件的实现示例
GoLang中拼接字符串性能优化方法详解
Python利用pynput实现划词复制功能
Python threading Local()函数用法案例详解
![](https://img.aspxhome.com/file/2023/4/72944_0s.jpg)
python禁用键鼠与提权代码实例
Python获取协程返回值的四种方式详解
![](https://img.aspxhome.com/file/2023/9/62869_0s.jpg)
python中matplotlib的颜色以及形状实例详解
![](https://img.aspxhome.com/file/2023/2/105592_0s.png)
详解Go语言如何使用标准库sort对切片进行排序
MySQL联合查询之轻松实现数据关联详解
![](https://img.aspxhome.com/file/2023/4/118464_0s.png)