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>

效果

ES6新语法Object.freeze和Object.seal基本使用

如果是未添加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

标签:ES6,语法,Object.freeze,Object.seal
0
投稿

猜你喜欢

  • python optparse模块使用实例

    2021-02-03 22:01:36
  • Mootools 1.2教程(19)——Tooltips

    2008-12-25 13:26:00
  • python绘制浅色范围曲线的示例代码

    2021-07-03 02:34:10
  • Python模块/包/库安装的六种方法及区别

    2021-11-03 15:53:56
  • vue实现动态路由详细

    2024-05-05 09:25:19
  • 使用线框图来简化你的产品设计流程

    2011-06-10 13:10:00
  • python argparser的具体使用

    2023-07-13 09:25:36
  • Python matplotlib实时画图案例

    2021-11-08 01:43:24
  • Git的基础文件操作初始化查看添加提交示例教程

    2023-12-25 19:43:21
  • numpy数组之存取文件的实现示例

    2021-02-20 11:32:57
  • GoLang中拼接字符串性能优化方法详解

    2024-04-28 09:16:46
  • Python利用pynput实现划词复制功能

    2022-03-28 23:14:23
  • Python threading Local()函数用法案例详解

    2021-11-27 21:57:02
  • python禁用键鼠与提权代码实例

    2022-12-11 11:54:59
  • Python获取协程返回值的四种方式详解

    2023-10-03 15:13:21
  • python中matplotlib的颜色以及形状实例详解

    2021-06-30 23:04:35
  • 详解Go语言如何使用标准库sort对切片进行排序

    2024-04-30 10:07:53
  • MySQL联合查询之轻松实现数据关联详解

    2024-01-15 09:27:14
  • Python 网络编程之UDP发送接收数据功能示例【基于socket套接字】

    2023-09-23 14:33:28
  • aspjpeg组件安装问题

    2008-09-27 17:52:00
  • asp之家 网络编程 m.aspxhome.com