摘要:很多編程語言提供了關鍵詞聲明一個常量,在中也是提供了,但是在前端的與其他編程語言不同,其并不意味著聲明的變量就是一個常量。所以,在前端中到底如何實現一個常量可以凍結對象,不能新增和刪除屬性,同時對象已有屬性都是不可枚舉不可配置不可寫。
很多編程語言提供了const關鍵詞聲明一個常量,在ES6中也是提供了const,但是在前端的const與其他編程語言不同,其并不意味著聲明的變量就是一個常量。使用const b = {}聲明了一個常量b,但是通過使用b.a = 1去修改對象b卻并沒有報錯,我們修改了一個原本以為是常量實際上是變量的對象。
為什么會這樣?
實際上,const定義的變量保存的是指向實際數據的指針,對于基本數據類型String、Boolean、Number、undefined、null、Symbol而言,
其值保存在棧內存中的簡單數據段,按值訪問,就是等同于常量。但是相對于引用數據類型而言,const只能保證指向保存在堆內存中的對象的指針保持不變,換句話說
const能夠保證變量始終指向同一個對象,至于對象的修改無能為力。
所以,在前端中到底如何實現一個常量!
Object.freezeObject.freeze可以凍結對象,不能新增和刪除屬性,同時對象已有屬性都是不可枚舉、不可配置、不可寫。需要注意的是使用該方法只能讓對象淺凍結,其內部屬性為對象時
依然能夠被篡改,要想實現完全凍結,那么就需要進行如下操作。
function deepConst(data){ Object.freeze(data); for(let key in data){ let prop = data[key]; if(!data.hasOwnProperty(key) || !(typeof prop === "object") || Object.isFrozen(prop)){ continue; } deepConst(prop); } }Object.defineProperty、Object.preventExtensions、Object.seal Object.preventExtensions
該方法可以將對象變為不可擴展即對象即不能添加新的屬性,但是對象的原有屬性依然可以被刪除或修改,同時如果屬性的值為對象,盡管設置了
不能被添加屬性,但是其屬性值為對象的屬性依舊可以添加屬性。
舉個例子:
let obj = {a:1,b:2,c:{d:3}}; Object.preventExtensions(obj); obj.d = 1; obj.a = 2; delete obj.b; obj.c.e = 10; //輸出{a:1,c:{d:3,e:10} console.log(obj);Object.seal
與Object.preventExtensions相比,該方法同樣能夠將對象變為不能添加新屬性,并且該方法禁止刪除對象的屬性。同樣如果屬性的值為對象,
屬性值依舊可以添加新屬性或刪除屬性。
舉個例子
let obj = {a:1,b:2,c:{d:3}}; Object.seal(obj); obj.e = 10; delete obj.a; delete obj.c.d; obj.c.f = 10; //輸出{a:1,b:2,c:{f:10} console.log(obj);Object.defineProperty
Object.defineProperty(obj, prop, descriptor)在MVVM中大放異彩,使用其也能夠將將對象完整凍結。在寫代碼之前我們
先了解下writable、Configurable需要知道都內容,這才是此次凍結的關鍵。
對象屬性的值是否能夠被重寫,為true表示允許,為false即被禁止,默認為false。如果屬性的值為對象,
盡管設置了不能被重寫,其屬性為對象的值依舊能夠被重寫。
舉個例子:
let obj = {a:1,b:2,c:{d:3}}; Object.defineProperty(obj,"a",{writable:true}); Object.defineProperty(obj,"b",{writable:false}); Object.defineProperty(obj,"c",{writable:false}); Object.defineProperty(obj,"e",{writable:false}); obj.a = 2; obj.b = 3; obj.c.d = 4; //輸出為2,即a屬性的值被重寫了 console.log(obj.a); //輸出依然為2,即b屬性的值沒有被重寫 console.log(obj.b); //輸出依然為{d:4},如果屬性的值為對象,盡管設置了不能被重寫,其屬性為對象的值依舊能夠被重寫。 console.log(obj.c);
configurable特性表示對象的屬性是否可以被刪除,以及除writable特性外的其他特性是否可以被修改。為true表示允許被修改
false表示禁止修改,默認為false,如果屬性的值為對象,盡管設置了屬性不能被修改,其屬性為對象的屬性依舊能夠被修改。
舉個例子
let obj = {a:1,b:2,c:{d:3}}; Object.defineProperty(obj,"a",{configurable:true}); Object.defineProperty(obj,"b",{configurable:false}); Object.defineProperty(obj,"c",{configurable:false}); delete obj.a; delete obj.b; delete obj.c; //輸出 {b:2,c:{}},如果屬性的值為對象,盡管設置了屬性不能被修改,其屬性為對象的屬性依舊能夠被修改。 console.log(obj);
上面這三個方法多帶帶拿出來并不能夠完美的將對象變為一個常量,但是我們組合一下就可以生成一個常量。
function deepConst(data){ if (!data || typeof data !== "object") { return; } //Object.preventExtensions(data);也可以實現 Object.seal(data); Object.keys(data).forEach(function(key) { unWriteConfig(data, key, data[key]); }); } function unWriteConfig(data, key, val) { deepConst(val); Object.defineProperty(data, key, { writable:false, configurable:false }); }Proxy
Proxy在目標對象之前進行了一層攔截,外界對對象的訪問和修改都需要通過這層攔截,所以我們可以操控攔截來控制對對象對訪問和修改。Proxy
支持的攔截操作眾多,下面只列舉與文章相關的操作,如果想更深入了解Proxy,請看這篇文章。
function createDeepProxy(target) { function makeHandler() { return { set(target, key, value, receiver) { return false; }, deleteProperty(target, key) { return false; } } } function proxify(obj, path) { for(let key of Object.keys(obj)) { if(typeof obj[key] === "object") { obj[key] = proxify(obj[key], [...path, key]); } } let p = new Proxy(obj, makeHandler()); return p; } return proxify(target, []); }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/102535.html
摘要:只要保證在開發中沒有對共享對象的寫入操作,那么發布到線上時肯定也沒有寫入操作,這時候這個保護方法就是多余的。 什么是共享對象 被多次使用到的同一個對象即為共享對象 比如我們用標準的es模塊來寫一個導出單位轉換的模塊 //converter module export default { cmToIn(){ //convert logic } } 當我們在...
摘要:是一個運行在瀏覽器端的腳本語言現在已經不僅僅局限于瀏覽器端是一門解釋型動態類型的語言解釋型指語言在執行時不需要編譯,由瀏覽器自動編譯基本語法區分大小寫是一種區分大小寫的語言定義變量名稱一般用小寫定義常量名稱一般用大寫空格和換行中會 JavaScript - JavaScript是一個運行在瀏覽器端的腳本語言(現在已經不僅僅局限于瀏覽器端) - JavaScript是一門解釋型、動態類型...
摘要:本期推薦文章類內存泄漏及如何避免,由于微信不能訪問外鏈,點擊閱讀原文就可以啦。四種常見的內存泄漏劃重點這是個考點意外的全局變量未定義的變量會在全局對象創建一個新變量,如下。因為老版本的是無法檢測節點與代碼之間的循環引用,會導致內存泄漏。 (關注福利,關注本公眾號回復[資料]領取優質前端視頻,包括Vue、React、Node源碼和實戰、面試指導) 本周正式開始前端進階的第一期,本周的主題...
摘要:語法常量名值常量名在程序中,通常采用大寫形式。結果為類型作用表示使用的數據不存在類型只有一個值即當聲明的變量未賦值未初始化時,該變量的默認值就是類型用于表示不存在的對象。結果為按位或,對小數取整將任意小數與做按位或,結果則取整數部分。 前端知識點總結——JS基礎 1.javascript概述(了解) 1.什么是javascript javascript簡稱為js,是一種運行于js解釋器...
閱讀 3616·2021-11-24 09:39
閱讀 2546·2021-11-15 11:37
閱讀 2211·2021-11-11 16:55
閱讀 5155·2021-10-14 09:43
閱讀 3703·2021-10-08 10:05
閱讀 3006·2021-09-13 10:26
閱讀 2327·2021-09-08 09:35
閱讀 3535·2019-08-30 15:55