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


猜你喜欢
- 我最近花了一些时间在探索CPython,并且我想要在这里分享我的一些冒险经历。Allison Kaptur的excellent guide
- Java 实现class PrimeNumber{public static void main(String[] args) {long
- 在爬取的过程中难免发生ip被封和403错误等等,这都是网站检测出你是爬虫而进行反爬措施,在这里为大家总结一下怎么用IP代理防止被封首先,设置
- 1.ResNet的创新现在重新稍微系统的介绍一下ResNet网络结构。 ResNet结构首先通过一个卷积层然后有一个池化层,然后通过一系列的
- 本文实例讲述了Python计算已经过去多少个周末的方法。分享给大家供大家参考。具体如下:def weekends_between(d1,d2
- @keyup.enter失效问题情况一(我遇到的情况)@keyup.enter外部存在form表单,并且form表单里只有一个input原因
- 环境配置系统:Windows10版本:python 3.8Turtle扫盲1.绘图窗体的设置turtle.setup(width, heig
- 这篇文章演示如何将训练好的pytorch模型部署到安卓设备上。我也是刚开始学安卓,代码写的简单。环境:pytorch版本:1.10.0模型转
- 开发背景是这样的:整个项目中使用很多台摩托罗拉的RFID读卡器,我要为这些读卡器写一个管理程序,判断是否有RFID标签进入或离开某个区域。用
- 基本开发环境· Python 3.6· Pycharm相关模块使用目标网页分析输入想看的小说内容,点击搜索这里会返回很多结果,我只选择第一个
- JS提供两个截取字符串的方法,分别是:slice()和substring()slice和substring都可以接受一个或两个参数,第1个参
- SQL Server 2008 备份数据库:1.打开SQL , 找到要备份的数据库 , 右键 >> 任务 >>备份2
- pprint的英文全称Data pretty printer,顾名思义就是让显示结果更漂亮。print()和pprint()都是python
- (应一些初学者的要求,虽然本人也绝对称不上专业,但是想让一个人快速地走出初学的迷茫,需要这种精炼的集合)首先,阐明一下我的观点:不论是什么编
- 前言在做项目的时候一些配置文件都会写在settings配置文件中,今天在研究"州的先生"开源文档写作系统-MrDoc的时
- 介绍获取协程返回值的四种方式:1、通过ensure_future获取,本质是future对象中的result方2、使用loop自带的crea
- 这篇文章主要介绍了如何基于python生成list的所有的子集,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,
- 本文实例讲述了python实现自动重启本程序的方法。分享给大家供大家参考。具体实现方法如下:#!/usr/local/bin/python#
- 测试用例(1) 测试用例(2)代码如下(python):# coding=utf-8from appium import webd
- 本文实例讲述了JS实现密码框根据焦点的获取与失去控制文字的消失与显示效果。分享给大家供大家参考,具体如下:思路:1、首先用把密码框用txt暂