深入理解ES6之——代理和反射(proxy)


通過調用new proxy()你可以創建一個代理來替代另一個對象(被稱為目標),這個代理對目標對象進行了虛擬,因此該代理與該目標對象表面上可以被當做同一個對象來對待。

創建一個簡單的代理

當你使用Proxy構造器來創建一個代理時,需要傳遞兩個參數:目標對象以及一個處理器,后者是定義了一個或多個陷阱函數的對象。如果未提供陷阱函數,代理會對所有操作采取默認行為。

使用set陷阱函數驗證屬性值

let target = {};
var proxy = new Proxy(target, {
    set(trapTarget, key, value, receiver) {
        if (!trapTarget.hasOwnProperty(key)) {
            if (isNaN(value)) {
                throw new Error('Proxy must be a number');
            }
        }

        return Reflect.set(trapTarget, key, value, receiver);
    }
})

proxy.count = 1;

console.log(proxy.count);
console.log(target.count);

try {
    proxy.anthorName = 'cc';
} catch (err) {
    console.log(err.message);
}

使用上述方法可以對添加給對象的屬性值進行驗證,如果值為非數字,就會拋出錯誤。

使用get陷阱函數進行對象外形驗證

在js中,如果讀取一個對象中不存在的屬性時,會顯示undefined,這對於排查問題很不利。使用代理進行對象外形驗證就可以幫你從這個錯誤中拯救出來。

let proxy = new Proxy({}, {
    get(trapTarget, key, receiver) {
        if (!(key in receiver)) {
            throw new Error(`property ${key} not exist`);
        }
        return Reflect.get(trapTarget, key, receiver);
    }
})

proxy.name = 'cc';
try {
    console.log(proxy.age);
} catch (error) {
    console.log(error.message);
}

//輸出結果
property age not exist

上述代碼對打印的對象屬性進行驗證,如果不存在則拋出一個錯誤。今日頭條的一個面試題

使用has陷阱函數隱藏屬性

in運算符用於判斷指定對象中是否存在某個屬性,如果對象的屬性名與指定的字符串或符號值相匹配,那么in運算符應當返回true,無論該屬性是對象自身的屬性還是原型的屬性。代理允許你使用has陷阱函數來解決這個問題

has陷阱函數會在使用in運算符的情況下被調用,並且會被傳入兩個參數:

  1. trapTarget:需要讀取屬性的對象(即代理的目標對象)
  2. key:需要檢查的屬性的鍵(字符串類型或符號類型)Reflect.has()方法接收與之相同的參數並向in運算符返回默認相應結果
let target = {
    name: 'cc',
    age: 26,
    sex: 'man'
}

let proxy = new Proxy(target, {
    has(trapTarget, key) {
        if (trapTarget.hasOwnProperty(key)) {
            return Reflect.has(trapTarget, key);
        } else {
            return false;
        }
    }
})

console.log('toString' in proxy);
console.log('name' in proxy);
console.log('age' in proxy);

使用deleteProperty陷阱函數避免屬性被刪除

delete運算符能從指定對象上刪除一個屬性,在刪除成功時返回true,否則返回false

deleteProperty陷阱函數會在使用delete運算符去刪除對象屬性時被調用,並且會被傳入兩個參數:

  1. trapTarget:需要刪除屬性的對象
  2. key:需要刪除的屬性的鍵

Reflect.deleteProperty()方法也接受兩個參數,並提供了deleteProperty陷阱函數的默認實現。

let target = {
    name: 'target',
    value: 42
}

let proxy = new Proxy(target, {
    deleteProperty(trapTarg, ke) {
        if (ke === 'value') {
            return false;
        } else {
            return Reflect.deleteProperty(trapTarg, ke);
        }
    }
})

let result = delete proxy.value;
let result1 = delete proxy.name;
console.log(result);
console.log(result1);

我的博客即將同步至騰訊雲+社區,邀請大家一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=2n9b6sotx9wkc


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM