Object definProperty基本使用 及 簡單實現 Vue 的雙向綁定原理及屬性代理

Object.definedProperty 能夠給對象添加一個屬性,或者修改一個已有的屬性,添加一些配置項數組

參數

const obj = {}

/**
* obj  源對象
* prop  要定義或修改的屬性的名稱或 Symbol 。
* descriptor  要定義或修改的屬性描述符。
*/
Object.defineProperty(obj, 'a', {
    value: 1,  // 值
    configurable: true,  // 當且僅當該屬性的 configurable 鍵值爲 true 時,該屬性的描述符纔可以被改變,同時該屬性也能從對應的對象上被刪除。 默認爲 false。
    writable: true,  // 是否可寫。默認爲 false
    enumerable: true, // 當且僅當該屬性的 enumerable 鍵值爲 true 時,該屬性纔會出如今對象的枚舉屬性中。默認爲 false
    get() {}, // 獲取值時觸發
    set() {} // 設置值時觸發
})
複製代碼

實現對一個對象的監聽,在訪問屬性、設置屬性時,打印出 'get xx attr' 'set xx attr'

var object = {
    a: 1,
    b: 2
}

for(let key in object) {
    let value = obj[key]

    Object.defineProperty(object, key, {
        configurable: true,
        enumerable: true,
        get() {
            console.log(`get ${key} attr`)
            return value
        },
        set(newValue) { 
            console.log(`set ${key} attr`)
            value = newValue
        }
    })
}

object.a    // get a attr
object.b = 3    // ser a atter 設置值的時候並不會觸發 get 方法
複製代碼

設置值的時候並不會觸發 get 方法bash

實現相似 Vue 的響應式代理

如訪問 this.a 實際訪問的是 this.$data.aui

var Vue = {
    $data: {
        a: 1,
        b: 2
    }
}

for(let key in Vue.$data) {
    let value = Vue.$data[key]

    Object.defineProperty(Vue, key, {
        configurable: true,
        enumerable: true,
        get() {
            return Vue.$data[key]
        },
        set(newValue) { 
            Vue.$data[key] = newValue
        }
    })
}

console.log(Vue.a, Vue.$data.a) // 1, 1
Vue.a = 2
console.log(Vue.a, Vue.$data.a) // 2, 2
Vue.$data.b = 3
console.log(Vue.b, Vue.$data.b) // 3, 3
複製代碼

簡單實現 Vue 中對數組的劫持處理

var arr = [1, {a: 1}, 3]

for (var i = 0; i < arr.length; i++) {
    if (typeof arr[i] === 'object' && arr[i] !== null) {
        for (let key in arr[i]) {
            let value = arr[i][key]

            Object.defineProperty(arr[i], key, {
                configurable: true,
                enumerable: true,
                get() {
                    console.log(`get ${key} attr`)
                    return value
                },
                set(newValue) {
                    console.log(`set ${key} attr`)
                    value = newValue
                }
            })
        }
    }
}

// arrPro 一個橋樑攔截了原生的 push 方法,而後在調用原生的 push 
// 攔截是由於防止原型鏈污染
var arrPro = Object.create(Array.prototype)
arr.__proto__ = arrPro

arrPro.push = function(argu) {
    if (typeof argu === 'object' && argu !== null) {
        for (let key in argu) {
            let value = argu[key]

            Object.defineProperty(argu, key, {
                configurable: true,
                enumerable: true,
                get() {
                    console.log(`get ${key} attr`)
                    return value
                },
                set(newValue) {
                    console.log(`set ${key} attr`)
                    value = newValue
                }
            })
        }
    }

    arrPro.__proto__.push.call(this, argu)
}

arr[0] = 0
arr[1].a = 'a'
// 使得添加的數據成響應式
arr.push({b: 2})
複製代碼

【筆記不易,如對您有幫助,請點贊,謝謝】this

相關文章
相關標籤/搜索