Object.defineProperty不能監聽數組長度變化,而Proxy可以監聽?

一、Object.defineProperty

MDN-Configurable中提到:
當且僅當該屬性的 configurable 爲 true 時,該屬性描述符才能夠被改變,同時該屬性也能從對應的對象上被刪除。默認爲 false。

首先對於數組,本身是因爲不可監聽length,造成了一系列push,pop等這種改變數組長度,無法監聽到。

var arr = [1,2,3]
Object.getOwnPropertyDescriptors(arr)

/*
=> {
    0:
        configurable: true
        enumerable: true
        value: 1
        writable: true
        __proto__: Object
    1:
        configurable: true
        enumerable: true
        value: 2
        writable: true
        __proto__: Object
    2:
        configurable: true
        enumerable: true
        value: 3
        writable: true
        __proto__: Object
    length:
        configurable: false
        enumerable: false
        value: 3
        writable: true
        __proto__: Object
}
*/

這裏可以明確的看到length 屬性的configurable是false,然後各大瀏覽器廠商包括JS本身,也不允許將length的configurable修改爲true,修改後會拋出VM305:1 Uncaught TypeError: Cannot redefine property: length的錯誤,所以造成了pop,push這種會修改原數組長度的值都無法被監聽到

而對於下面這種是可以的

var obj = {},
    temp = 1
Objcet.defineProperty(obj,'list',{
  set:function(value){
    console.log("setted");
    value = 1;
  },
  get:function(){
    return temp;
  }
});
obj.list = []; // setted
obj.list = [1,2,3]; // setted

因爲這種是將一個新數組賦給obj.list, 而不是修改原數組

二、Proxy

MDN-Proxy中提到:
target
  代理虛擬化的對象。它通常用作代理的存儲後端。根據目標驗證關於對象不可擴展性或不可配置屬性的不變量(保持不變的語義)。

Array.length 就是不可配置的屬性,故Proxy可以監聽原數組中長度的變化。

三、Vue3

// vue3 使用

const reactive = new Proxy([1,2,3], handlers) // handlers 爲內置getter、setter、has等函數

const arr = reactive([1,2,3]);

通過reactive函數, 將[1,2,3]包裝成響應式對象,即Proxy對象,所以你可以通過push,pop等改變原數組長度的方法去實現監聽

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章