天天看點

Javascript Proxy對象 簡介Javascript Proxy對象 簡介Javascript Proxy對象

Javascript Proxy對象 簡介

本文轉載自: 衆成翻譯 譯者: eJayYoung 連結: http://www.zcfy.cc/article/4755 原文: https://blog.campvanilla.com/advanced-guide-javascript-proxy-objects-introduction-301c0fce9432

Javascript Proxy對象

改變你操作對象的方式

Javascript Proxy對象 簡介Javascript Proxy對象 簡介Javascript Proxy對象
Proxies 是Javasript對象的中間件

…或者說至少是那種很早的版本。

ES6 中引入Proxies,讓你可以自定義

Object

的基本操作。例如,

get

就是

Object

的基礎操作方法。

const obj = {
   val: 10
};
           
console.log(obj.val);
           

這裡,

console.log()

表達式在對象

obj

上執行

get

方法來擷取

val

的值。

另一個對象的基本操作方法是

set

const obj = {
   val: 10
};
           
obj.val2 = 20;
           

set

方法用來給對象

obj

設定一個新的值。

如何建立Proxy?

const proxiedObject = new Proxy(initialObj, handler);
           

調用Proxy構造函數,

new Proxy()

将傳回一個對象,不僅包含了

initialObj

裡的值,而且其基本操作(如

get

set

)現在可以通過

handler

對象來指定一些自定義邏輯。

我們寫個例子來了解這個概念,

const handler = {
    get: function() {
        console.log('A value has been accessed');
    }
}

const initialObj = {
    id: 1,
    name: 'Foo Bar'
}

const proxiedObj = new Proxy(initialObj, handler);

console.log(proxiedObj.name);           

現在,如果我們沒有構造一個Proxy對象,執行第14行的

console.log(proxiedObj.name)

會在控制台輸出 “Foo Bar”。

不過現在我們定義了一個Proxy,并在第三行

get

方法中定義了一些自定義邏輯。

現在執行

console.log(proxiedObj.name)

會在控制台輸出 “A value has been accessed”。

Javascript Proxy對象 簡介Javascript Proxy對象 簡介Javascript Proxy對象

仔細看,你會發現控制台中實際上有兩條記錄。 “A value has been accessed” 和

undefined

。 為什麼?��

get

運算符的預設實作是傳回Object中存儲的值。由于我們将它重寫為隻記錄一條語句,該值永遠不會傳回,是以第14行的

console.log()

輸出

undefined

讓我們來解決這個問題!

get

運算符有兩個參數 - 對象本身和被通路的屬性。

const handler = {
    get: function(obj, prop) {
        console.log('A value has been accessed');
        return obj[prop]; // 傳回通路的key在obj的值
    }
}

const initialObj = {
    id: 1,
    name: 'Foo Bar'
}

const proxiedObj = new Proxy(initialObj, handler);

console.log(proxiedObj.name);           

傳回屬性值

Javascript Proxy對象 簡介Javascript Proxy對象 簡介Javascript Proxy對象

傳回屬性值 — 控制台的輸出

好多了吧! ��

我們為

get

提供的自定義覆寫被稱為“攔截器”(大概基于

作業系統攔截

的概念)。

handler

對象基本上是一個包含一組“攔截”的對象,每當通路對象屬性時都會被觸發。

我們給

set

也添加一個“攔截器”。 我們将做同樣的事情 - 任何時候設定一個值,我們将記錄被修改的屬性,以及為該鍵設定的值。

set

操作符有三個參數 - 對象本身,被通路的屬性和為該屬性設定的值。

const handler = {
    get: function(obj, prop) {
        console.log('A value has been accessed');
        return obj[prop];
    },
    set: function(obj, prop, value) {
        console.log(`${prop} is being set to ${value}`);
    }
}

const initialObj = {
    id: 1,
    name: 'Foo Bar'
}

const proxiedObj = new Proxy(initialObj, handler);

proxiedObj.age = 24           

添加

set

“攔截器”

這裡,在第18行進行的通路将觸發第6行定義的功能,該功能将記錄正在通路的屬性和正在設定的值。

Javascript Proxy對象 簡介Javascript Proxy對象 簡介Javascript Proxy對象

Set

“攔截器” —— 控制台的輸出

一個真實的例子

假設我們有一個定義叫person的對象

const person = {
   id: 1,
   name: 'Foo Bar'
};
           

如果我們想讓這個對象的id屬性是一個私有屬性呢? 沒人能夠通過person.id通路這個屬性,如果有人這樣做,我們需要抛出一個錯誤。 我們将如何做到這一點?

讓Proxies來拯救吧!����‍��

我們所需要做的就是給這個對象建立一個Proxy,并覆寫

get

運算符來阻止我們通路

id

屬性!

const handler = {
    get: function(obj, prop) {
        if (prop === 'id') { // Check if the id is being accessed
            throw new Error('Cannot access private properties!'); // Throw an error
        } else {
            return obj[prop]; // If it's not the id property, return it as usual
        }
    }
}

const person = {
    id: 1,
    name: 'Foo Bar'
}

const proxiedPerson = new Proxy(person, handler);

console.log(proxiedPerson.id);           

阻止通路私有屬性

這裡,在我們給

get

建立的“攔截器”,我們檢查被通路的屬性是否是

id

屬性,如果是的話,我們會抛出一個錯誤。 否則,我們照常傳回值。

Javascript Proxy對象 簡介Javascript Proxy對象 簡介Javascript Proxy對象

私有屬性 — 控制台輸出

另一個極好的用例是校驗。 通過設定

set

“攔截器”,我們可以在設定值之前添加自定義驗證。 如果該值不符合驗證,我們可以抛出一個錯誤!

const handler = {
    set: function(obj, prop, value) {
        if (typeof value !== 'string') {
            throw new Error('Only string values can be stored in this object!');
        } else {
            obj[prop] = value;
        }
    }
}

const obj = {};

const proxiedObj = new Proxy(obj, handler);

console.log(proxiedObj); // This will log an empty object
proxiedObj.name = 'Foo Bar'; // This should be allowed
console.log(proxiedObj); // This will log an object with the name property set

proxiedObj.age = 24; // This will throw an error.           

自定義對象的屬性校驗

Javascript Proxy對象 簡介Javascript Proxy對象 簡介Javascript Proxy對象

自定義校驗 - 控制台輸出

在上面的例子中,我們已經看到了

get

set

“陷阱”。 實際上可以設定更多的“陷阱”。 你可以在這裡找到

整個清單

Proxy對象隻是在閱讀

關于它們的這篇文章

之後才進入我的視野,我已經可以在我每天寫的代碼中看到它們的用處了!

如果你之前在項目或工作中使用過Proxies,我很樂意聽到!��

~最後~

如果您覺得這篇文章對您有用,請點個贊��!

在什麼地方卡住了,需要更多的幫助,還是隻想打個招呼? 在

Hashnode

給我直接發問題,或者在

Twitter

上Call我。 你也可以在

Github

上找到我。��

繼續閱讀