ES6新語法Object.freeze和Object.seal基本使用
引言
隨著ES6新語法的不斷迭代更新,已經(jīng)出現(xiàn)了許多常用的工具api。今天我將為大家推薦兩款明星api,它們就是Object.freeze和Object.seal。究竟它兩可以帶給我們怎樣的驚喜?我只能用兩個(gè)字形容:NB
Object.freeze
1.基本使用
首先從單詞含義分析 freeze代表冰凍,嗯那這個(gè)api就是冰凍/凍結(jié)對象的意思。接著我們看看mdn的解釋吧
MDN官方解釋
Object.freeze()
方法可以凍結(jié)一個(gè)對象。一個(gè)被凍結(jié)的對象再也不能被修改;凍結(jié)了一個(gè)對象則不能向這個(gè)對象添加新的屬性,不能刪除已有屬性,不能修改該對象已有屬性的可枚舉性、可配置性、可寫性,以及不能修改已有屬性的值。
官方就是踏馬官方啊,解釋的我都懷疑自己沒學(xué)過語文,繞來繞去。其實(shí)它就說了一句話,Object.freeze可以讓一個(gè)對象無法增加新屬性,無法刪除已有屬性,無法修改已有屬性。本質(zhì)就是指目標(biāo)對象只能讀,其它任何操作都無效。
功能演示
通過Object.freeze處理的對象,進(jìn)行刪除,添加,修改都是無效的,并且在非嚴(yán)格模式下是不會(huì)報(bào)錯(cuò)的。
let obj = {name:"dzp",age:22} Object.freeze(obj) obj.name = "dzp2"http://修改無效 delete obj.age//刪除無效 obj.a = 1//添加無效 console.log(obj)// {name:"dzp",age:22}
拓展
看到上面的操作,部分童鞋可能疑問這個(gè)對數(shù)組可以凍結(jié)?數(shù)組在js里面也屬于對象,所以數(shù)組也是可以凍結(jié)的。凍結(jié)后的數(shù)組也是只讀的
let arr = [1] Object.freeze(arr) arr[0] = 2//無效 arr.push(2)//無效 arr.shift()//無效 console.log(arr)//[1]
2.Object.freeze與const對比
看到freeze大家肯定會(huì)聯(lián)想到另一個(gè)api,它就是const。它們感覺都有凍結(jié)的意思,其實(shí)二者設(shè)計(jì)初衷和功能點(diǎn)還是相差甚遠(yuǎn)。
const通常我們用它修飾普通變量,用const定義的普通變量值無法修改。而const定義的對象地址無法修改,其內(nèi)部的屬性仍然是可變的。
const定義普通變量
const a = 10 a = 20//error,報(bào)錯(cuò)無法修改
const定義對象
const obj = {a:1} obj.a = 2//ok obj = {}//error,報(bào)錯(cuò),不能修改地址
二者對比總結(jié)
- const通常定義普通變量,而Object.freeze通常定義對象
- const定義普通變量時(shí),值無法修改。定義對象時(shí),地址無法修改,但是對象內(nèi)部屬性可以任意改變。
- Object.freeze修飾的對象只能讀,其它任何操作都是無效的。
- Object.freeze修飾的對象可以改變地址,改變地址后的對象就失去了freeze控制了,當(dāng)然這個(gè)操作是毫無意義的。
3.常用功能
下面簡單列舉下Object.freeze的常用小功能吧。
- 凍結(jié)目標(biāo)對象(默認(rèn)是淺凍結(jié))
- vue2中數(shù)據(jù)的性能優(yōu)化
功能一:凍結(jié)目標(biāo)對象
看到這,估計(jì)有人要噴了。凍結(jié)對象不是很明顯的?還要介紹一遍?大哥,大姐們稍安勿躁。容我慢慢狡辯。
Object.freeze凍結(jié)對象是淺度凍結(jié),并非深度凍結(jié)。通常我們希望一個(gè)對象數(shù)據(jù)是完全只讀的。而單純的使用Object.freeze是無法實(shí)現(xiàn)對象完全可讀。
淺凍結(jié)示例
let obj = {name:"dzp",a:{b:1}} Object.freeze(obj) obj.name = "dzp2"http://無法修改 obj.a.b = 2//可以修改 console.log(obj)//{name:"dzp",a:{b:2}}
看到上面的結(jié)果大家就很容易發(fā)現(xiàn),freeze對對象的凍結(jié)只能作用到第一層上,當(dāng)對象層級(jí)大于等于2時(shí),后面的凍結(jié)就失效了。這其實(shí)就是淺凍結(jié),淺凍結(jié)和淺比較可以理解成一類,其中React函數(shù)組件通常我們會(huì)使用memo進(jìn)行優(yōu)化,此處的設(shè)計(jì)就是利用淺比較完成的。
深度凍結(jié)對象
上面我們知道了用freeze只能對對象進(jìn)行淺度凍結(jié),無法真正凍結(jié)一個(gè)多層嵌套對象的對象。通常我們需要自己設(shè)計(jì)深凍結(jié)。如下例子內(nèi)部出現(xiàn)了Object.seal。大家不必著急,可以先看完后面Object.seal的介紹,然后再繼續(xù)看深凍結(jié)例子。(Object.seal后面講更清晰)
功能二:vue2數(shù)據(jù)優(yōu)化
Object.freeze是如何對vue2的數(shù)據(jù)做到優(yōu)化?我們清楚vue2的data數(shù)據(jù)都是具備響應(yīng)式的,數(shù)據(jù)通過defineProperty完成響應(yīng)式設(shè)置,但是這本身耗費(fèi)了一定性能。如果我們有接口數(shù)據(jù)僅僅做展示并且數(shù)目較多。那么對其進(jìn)行響應(yīng)式監(jiān)聽無疑是沒必要的。但是vue2渲染界面的數(shù)據(jù)都是響應(yīng)式的,如何消除數(shù)據(jù)的響應(yīng)式?Object.freeze就可以做到消除響應(yīng)式。
<template> <div id="app"> <div v-for="item in list" :key=item>{{item}}</div> <div @click="changeData()">修改數(shù)據(jù)</div> </div> </template> <script> export default { name: 'App', data() { return { list:[] } }, mounted(){ //模擬接口獲取數(shù)據(jù) setTimeout(() => { this.list.push(...[1,2,3,4,5]) //將數(shù)據(jù)取消響應(yīng)式 Object.freeze(this.list) }, 2000); }, methods:{ changeData () { this.list.push(6) } } } </script>
效果
如果是未添加Object.freeze的數(shù)組,此處肯定是正常顯示6個(gè),但是通過freeze我們直接消除了數(shù)據(jù)的響應(yīng)式,讓這個(gè)數(shù)據(jù)只能展示而無法修改,同時(shí)也一定程度提升了性能。
Object.seal
Object.seal其實(shí)沒有Object.freeze使用的頻繁,但是一些工具還是需要它的配合,例如使用Object.seal可以模擬Object.freeze的淺度和深度的對象監(jiān)聽。
1.基本使用
MDN介紹
Object.seal()
方法封閉一個(gè)對象,阻止添加新屬性并將所有現(xiàn)有屬性標(biāo)記為不可配置。當(dāng)前屬性的值只要原來是可寫的就可以改變。
還是簡單總結(jié)官方的話語:Object.seal修飾的對象無法添加或者刪除屬性,可以修改可以讀取。
簡單使用
let obj = {name:"dzp"} Object.seal(obj) obj.age = 22//無法添加 obj.name = "dzp2"http://可以修改 delete obj.name//無法刪除 console.log(obj)//{name:"dzp2"}
值得注意的是Object.freeze和Object.seal都是對對象淺控制,只作用于第一層。大于等于2層級(jí)的對象不受控制。
let obj = {name:'dzp',a:{b:1}} delete obj.a.b console.log(obj)//{ name: 'dzp', a: {} }
2.模擬Object.freeze
模擬Object.freeze是一道經(jīng)典的面試手撕代碼題,我們可以借助Object.seal輕松的完成設(shè)計(jì)。整體設(shè)計(jì)還是比較簡單,使用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"http://無效 delete obj.name//無效 obj.age = 22//無效 obj.a.b = 2//有效,只凍結(jié)第一層 console.log(obj)//{name:"dzp",a:{b:2}}
3.模擬Object.freeze,同時(shí)保證對象深凍結(jié)
深度凍結(jié)在淺度凍結(jié)的基礎(chǔ)上,只需要加一個(gè)遞歸就可以實(shí)現(xiàn),整體設(shè)計(jì)十分清晰簡單。
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"http://無效 delete obj.name//無效 obj.age = 22//無效 obj.a.b = 2//無效,深凍結(jié)了 console.log(obj)//{name:"dzp",a:{b:2}}
總結(jié)
終于總結(jié)完了Object.freeze和Object.seal。
以上就是ES6新語法Object.freeze和Object.seal基本使用的詳細(xì)內(nèi)容,更多關(guān)于ES6語法Object.freeze Object.seal的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
跟我學(xué)習(xí)javascript的call(),apply(),bind()與回調(diào)
跟我學(xué)習(xí)javascript的call(),apply(),bind()與回調(diào),感興趣的小伙伴們可以參考一下2015-11-11bootstrap-table.js擴(kuò)展分頁工具欄(增加跳轉(zhuǎn)到xx頁)功能
這篇文章主要介紹了bootstrap-table.js擴(kuò)展分頁工具欄,增加跳轉(zhuǎn)到xx頁功能,由于小編的水平停留在dom級(jí),此次擴(kuò)展只支持頁面上的表格,如果大家有好的建議歡迎提出2017-12-12怎樣用JavaScript實(shí)現(xiàn)原型模式
這篇文章主要介紹了怎樣用JavaScript實(shí)現(xiàn)原型模式,想學(xué)習(xí)設(shè)計(jì)模式的同學(xué),可以參考下2021-04-04JS來動(dòng)態(tài)的修改url實(shí)現(xiàn)對url的增刪查改
通過get方式提交post表單等方式來動(dòng)態(tài)修改url存在諸多的不妥,因此,想到了通過JS來動(dòng)態(tài)的修改url,來實(shí)現(xiàn)對url的增刪查改2014-09-09基于HTML+JavaScript實(shí)現(xiàn)中國象棋
這篇文章主要為大家詳細(xì)介紹了如何利用HTML+CSS+JS實(shí)現(xiàn)中國象棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08JavaScript開發(fā)簡單易懂的Svelte實(shí)現(xiàn)原理詳解
這篇文章主要為大家介紹了JavaScript開發(fā)簡單易懂的Svelte實(shí)現(xiàn)原理的內(nèi)容詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-11-11