ES6新語法Object.freeze和Object.seal基本使用
引言
隨著ES6新語法的不斷迭代更新,已經(jīng)出現(xiàn)了許多常用的工具api。今天我將為大家推薦兩款明星api,它們就是Object.freeze和Object.seal。究竟它兩可以帶給我們怎樣的驚喜?我只能用兩個字形容:NB
Object.freeze
1.基本使用
首先從單詞含義分析 freeze代表冰凍,嗯那這個api就是冰凍/凍結(jié)對象的意思。接著我們看看mdn的解釋吧
MDN官方解釋
Object.freeze() 方法可以凍結(jié)一個對象。一個被凍結(jié)的對象再也不能被修改;凍結(jié)了一個對象則不能向這個對象添加新的屬性,不能刪除已有屬性,不能修改該對象已有屬性的可枚舉性、可配置性、可寫性,以及不能修改已有屬性的值。
官方就是踏馬官方啊,解釋的我都懷疑自己沒學(xué)過語文,繞來繞去。其實它就說了一句話,Object.freeze可以讓一個對象無法增加新屬性,無法刪除已有屬性,無法修改已有屬性。本質(zhì)就是指目標對象只能讀,其它任何操作都無效。
功能演示
通過Object.freeze處理的對象,進行刪除,添加,修改都是無效的,并且在非嚴格模式下是不會報錯的。
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}
拓展
看到上面的操作,部分童鞋可能疑問這個對數(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大家肯定會聯(lián)想到另一個api,它就是const。它們感覺都有凍結(jié)的意思,其實二者設(shè)計初衷和功能點還是相差甚遠。
const通常我們用它修飾普通變量,用const定義的普通變量值無法修改。而const定義的對象地址無法修改,其內(nèi)部的屬性仍然是可變的。
const定義普通變量
const a = 10 a = 20//error,報錯無法修改
const定義對象
const obj = {a:1}
obj.a = 2//ok
obj = {}//error,報錯,不能修改地址
二者對比總結(jié)
- const通常定義普通變量,而Object.freeze通常定義對象
- const定義普通變量時,值無法修改。定義對象時,地址無法修改,但是對象內(nèi)部屬性可以任意改變。
- Object.freeze修飾的對象只能讀,其它任何操作都是無效的。
- Object.freeze修飾的對象可以改變地址,改變地址后的對象就失去了freeze控制了,當(dāng)然這個操作是毫無意義的。
3.常用功能
下面簡單列舉下Object.freeze的常用小功能吧。
- 凍結(jié)目標對象(默認是淺凍結(jié))
- vue2中數(shù)據(jù)的性能優(yōu)化
功能一:凍結(jié)目標對象
看到這,估計有人要噴了。凍結(jié)對象不是很明顯的?還要介紹一遍?大哥,大姐們稍安勿躁。容我慢慢狡辯。
Object.freeze凍結(jié)對象是淺度凍結(jié),并非深度凍結(jié)。通常我們希望一個對象數(shù)據(jù)是完全只讀的。而單純的使用Object.freeze是無法實現(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)對象層級大于等于2時,后面的凍結(jié)就失效了。這其實就是淺凍結(jié),淺凍結(jié)和淺比較可以理解成一類,其中React函數(shù)組件通常我們會使用memo進行優(yōu)化,此處的設(shè)計就是利用淺比較完成的。
深度凍結(jié)對象
上面我們知道了用freeze只能對對象進行淺度凍結(jié),無法真正凍結(jié)一個多層嵌套對象的對象。通常我們需要自己設(shè)計深凍結(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è)置,但是這本身耗費了一定性能。如果我們有接口數(shù)據(jù)僅僅做展示并且數(shù)目較多。那么對其進行響應(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個,但是通過freeze我們直接消除了數(shù)據(jù)的響應(yīng)式,讓這個數(shù)據(jù)只能展示而無法修改,同時也一定程度提升了性能。
Object.seal
Object.seal其實沒有Object.freeze使用的頻繁,但是一些工具還是需要它的配合,例如使用Object.seal可以模擬Object.freeze的淺度和深度的對象監(jiān)聽。
1.基本使用
MDN介紹
Object.seal()方法封閉一個對象,阻止添加新屬性并將所有現(xiàn)有屬性標記為不可配置。當(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層級的對象不受控制。
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è)計。整體設(shè)計還是比較簡單,使用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,同時保證對象深凍結(jié)
深度凍結(jié)在淺度凍結(jié)的基礎(chǔ)上,只需要加一個遞歸就可以實現(xiàn),整體設(shè)計十分清晰簡單。
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基本使用的詳細內(nèi)容,更多關(guān)于ES6語法Object.freeze Object.seal的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JS復(fù)制內(nèi)容到剪切板的實例代碼(兼容IE與火狐)
這篇文章主要介紹了JS復(fù)制內(nèi)容到剪切板的實例代碼(兼容IE與火狐)。需要的朋友可以過來參考下,希望對大家有所幫助2013-11-11
js函數(shù)參數(shù)設(shè)置默認值的一種變通實現(xiàn)方法
js函數(shù)中有個儲存參數(shù)的數(shù)組arguments,因此js版支持參數(shù)默認值的函數(shù)可以通過另外一種變通的方法實現(xiàn)2014-05-05
詳解微信小程序-掃一掃 wx.scanCode() 掃碼大變身
這篇文章主要介紹了微信小程序-掃一掃wx.scanCode() 掃碼大變身,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
微信小程序云開發(fā)如何實現(xiàn)數(shù)據(jù)庫自動備份實現(xiàn)
這篇文章主要介紹了小程序云開發(fā) 數(shù)據(jù)庫自動備份實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-08-08

