1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        【每日一題】如何設置對象的屬性不可添加或刪除

        共 5017字,需瀏覽 11分鐘

         ·

        2021-09-02 01:55

        人生苦短,總需要一點儀式感。比如學前端~

        如何設置對象不可添加或者刪除屬性

        一共有如下幾種方式:

        1. Object.defineProperty()
        2. Object.seal()
        3. Object.freeze()
        4. Proxy

        前置知識:對象屬性的數(shù)據(jù)描述符

        對象的屬性有幾個數(shù)據(jù)描述符:

        1. configurable 表示是否可配置,作用有2:
          • 屬性數(shù)據(jù)描述符是否可被改變 (除value和writable特性外的其他描述符)
          • 屬性是否可被刪除
        2. enumerable: 表示屬性是否可枚舉
        3. value 表示屬性的值
        4. writable 表示屬性的值是否可以修改

        默認值

        使用 Object.defineProperty() 添加的屬性值是不可修改(immutable)的。
        這主要和幾個屬性的默認值有關:

        const object1 = {};

        Object.defineProperty(object1, 'property1', {
        });
        // 不填寫屬性數(shù)據(jù)描述符的前提下,獲取生成的描述符默認值
        console.log(Object.getOwnPropertyDescriptor(object1, 'property1'))
        屬性描述符默認值

        查看對象屬性描述符

        Object.getOwnPropertyDescriptor() 方法,用來查看指定對象上某個非原型屬性的屬性描述符。

        特別記憶:

        對象屬性的 configurable 鍵值為 true 時,該屬性的描述符才能夠被改變,同時該屬性也能從對應的對象上被刪除。

        當試圖改變不可配置屬性的值時 (除了 value 和 writable 屬性之外) ,會拋出TypeError,除非當前值和新值相同。

        嘗試修改導致的報錯

        實現(xiàn)方法講解如下

        defineProperty、defineProperties

        根據(jù)上邊屬性描述符的作用我們可以推斷,如果將 configurable 的值為 false 的時候,屬性就無法從對象上刪除。

        Object.defineProperty(obj, "name", {
          configurablefalse// 當且僅當該屬性的 configurable 鍵值為 true 時,該屬性的描述符才能夠被改變,同時該屬性也能從對應的對象上被刪除。
          enumerablefalse// 當且僅當該屬性的 enumerable 鍵值為 true 時,該屬性才會出現(xiàn)在對象的枚舉屬性中。
          writablefalse// 表示是否可以修改屬性的值。
          value"小石頭"// 該屬性(name)對應的值??梢允侨魏斡行У?JavaScript 值(數(shù)值,對象,函數(shù)等)。
        });

        像上邊代碼這樣設置之后,name屬性就變成了不能刪除、不可重新修改特性、不可枚舉、不能修改屬性值的狀態(tài)。

        但是只這么設置的話,目前obj對象只實現(xiàn)了元素無法被刪除,我們還是能往對象中添加新的屬性。

        obj.address = "beijing";
        console.log(obj); // { address: "beijing", name: "小石頭" }

        Object.seal()

        一個對象是可擴展的(可以添加新的屬性)。而Object.seal()方法會封閉一個對象:

        • 阻止添加新屬性
        • 并將所有現(xiàn)有屬性標記為不可配置(即不可刪除和不可修改屬性的某幾個數(shù)據(jù)描述符)。
        • 不過,當前屬性的值只要原來是可寫的就可以改變。也就是說屬性的值仍然可以修改。

        嘗試刪除一個密封對象的屬性或者將某個密封對象的屬性從數(shù)據(jù)屬性轉換成訪問器屬性,結果會靜默失敗或拋出 TypeError (在嚴格模式中最常見的,但不唯一)。

        const obj = { name"小石頭" };
        Object.getOwnPropertyDescriptors(obj);
        查看屬性數(shù)據(jù)描述符

        封閉對象:

        Object.seal(obj);
        Object.getOwnPropertyDescriptors(obj);
        封閉普通對象后的效果

        這時如果再去配置就失效了

        Object.defineProperty(obj, "name", {
          configurabletrue
        });
        Object.getOwnPropertyDescriptors(obj);
        configurable 已經(jīng)不可以配置、屬性也不可刪除了

        同時也沒法添加新屬性了

        obj.age = 18
        對象也不可添加新屬性了

        Object.freeze()

        Object.freeze() 方法可以凍結一個對象。凍結后的對象有如下特點:

        • 一個被凍結的對象再也不能被修改;
        • 不能向凍結對象添加新的屬性,
        • 不能刪除凍結對象的已有屬性,
        • 不能修改凍結對象已有屬性的可枚舉性、可配置性、可寫性以及不能修改已有屬性的值。
        • 此外,凍結一個對象后該對象的原型也不能被修改。

        ??注意:Object.freeze()方法實現(xiàn)的是淺凍結

        const obj = {
          name"小石頭",
          info: {
            address"beijing",
          },
        };
        const freezeObj = Object.freeze(obj); // freeze()返回和傳入的參數(shù)相同的對象
        // 不能修改凍結對象已有屬性值
        freezeObj.name = "石頭姐";
        console.log(freezeObj.name); // 仍然是小石頭
        // 不能往凍結對象新加內容
        freezeObj.newName = '石頭姐'
        console.log(freezeObj.name); // undefined,增加失敗
        // 刪除凍結對象的已有屬性也不成功
        delete freezeObj.name
        console.log(freezeObj.name); // 仍然是小石頭
        凍結后的對象和原對象看上去沒啥區(qū)別

        嚴格模式下,操作凍結對象的屬性會報錯

        ("use strict");
        freezeObj.name = "石頭姐"// TypeError
        //Uncaught TypeError: Cannot assign to read only property 'name' of object '#<Object>'
        報錯

        深層嵌套的對象沒有被凍結:

        // 在這里,info 是沒有被凍結的
        freezeObj.info.newName = "BJ";
        console.log(freezeObj.info.newName); // BJ

        ES6 的 Proxy 方法

        ?

        Proxy 可以理解成,在目標對象之前架設一層“攔截”,外界對該對象的訪問,都必須先通過這層攔截,因此提供了一種機制,可以對外界的訪問進行過濾和改寫。
        From:https://es6.ruanyifeng.com/#docs/proxy

        ?

        它在 API 使用者和對象之間扮演了一個中間人的角色。我們可以使用 Proxy 來控制被訪問的底層對象的屬性的行為。

        const target = {
          a"我是不能刪除的",
          b"我是不能修改的",
          c"也不能添加,我只有3個元素",
        };
        const lockTraget = new Proxy(target, {
          // 攔截對象屬性的設置,返回false不讓設置屬性
          set(target, property, value) {
            console.log("攔截修改、新增操作", target, property, value);
            return false;
          },
          // 攔截delete proxy[propKey]的操作,返回false不讓刪除
          deleteProperty(target, property) {
            console.log("攔截刪除操作");
            return false;
          },
          // 攔截Object.defineProperty()、Object.defineProperties()操作,
          defineProperty(target, property, descriptor) {
            console.log("defineProperty()");
            return false;
          },
        });
        lockTraget.newName = "石頭姐";
        console.log(lockTraget.newName); // undefined,新增失敗

        delete lockTraget.a;
        console.log(lockTraget.a); // "我是不能刪除的", 刪除失敗

        lockTraget.b = '小石頭'
        console.log(lockTraget.b); // "我是不能修改的", 修改失敗

        最后,我們掙扎的想用Object.defineProperty修改屬性數(shù)據(jù)描述符,也報錯了


        END
        愿你歷盡千帆,歸來仍是少年。


        讓我們一起攜手同走前端路!

        關注公眾號回復【加群】即可

        ● 工作中常見頁面布局的n種實現(xiàn)方法

        ● 三欄響應式布局(左右固寬中間自適應)的5種方法

        ● 兩欄自適應布局的n種實現(xiàn)方法匯總

        ● 工作中常見的兩欄布局案例及分析

        ● 垂直居中布局的一百種實現(xiàn)方式

        ● 常用九宮格布局的幾大方法匯總

        ● 為什么操作DOM會影響WEB應用的性能?

        ● 移動端滾動穿透的6種解決方案

        ● Vue + TypeScript 踩坑總結

        瀏覽 139
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            日屄欧美 | 一边做一边喷水 | 亚洲欧美国产另类 | 日韩精品乱| 短裙公车被强好爽h500 | 波多野结衣av一区二区全免费观看 | 我把美女日出了白浆 | 国产三级做爰在线播放五魁 | 欧美有码在线 | 久久人人爽人人人人片 |