發(fā)布于:2021-01-24 00:00:57
0
99
0
我一直都很喜歡JavaScript中對(duì)象和原型的靈活性,但很長(zhǎng)一段時(shí)間以來(lái),我覺(jué)得缺乏一定程度的動(dòng)態(tài)性。JavaScript最終為對(duì)象屬性添加了get和set方法,這是一個(gè)很棒的步驟,但仍然有改進(jìn)的空間。
JavaScript代理API是一個(gè)令人敬畏的改進(jìn):一個(gè)控制對(duì)象修改行為的虛擬化接口!
代理的格式
代理接受一個(gè)要代理的對(duì)象,以及一個(gè)帶有g(shù)et、set、has和其他常見(jiàn)對(duì)象方法處理程序(“陷阱”)的對(duì)象:
const proxy = new Proxy({}, { get: (obj, prop) => { ... }, set: (obj, prop, value) => { ... }, // more props here });
任何設(shè)置或獲取屬性的嘗試都將通過(guò)該陷阱運(yùn)行,從而允許您運(yùn)行額外的邏輯,特別是當(dāng)該屬性不需要、不存在或需要驗(yàn)證時(shí)。
基本用法
讓我們創(chuàng)建一個(gè)基本的代理,為任何給定的屬性返回默認(rèn)值:
const proxy = new Proxy({}, { get: (obj, prop) => { return prop in obj ? obj[prop] : null; } }); // proxy.whatever => null
上面的示例說(shuō)明了,無(wú)論代碼試圖設(shè)置什么屬性,您的代理邏輯都可以根據(jù)需要捕獲并修改它。對(duì)于不存在的屬性,可以返回null,而不是undefined。
驗(yàn)證
代理最明顯和最有用的用法是驗(yàn)證;由于您可以監(jiān)視并驗(yàn)證傳入的任何屬性,所以可以盡可能地保持?jǐn)?shù)據(jù)的純粹性。
const proxy = new Proxy({}, { set: (obj, prop, value) => { // Don't allow age > 100 if (prop === "age" && value > 100) { // Set to max age value = 100; } obj[prop] = value; } }); proxy.age = 120; proxy.age; // 100
你可以選擇像上面的例子那樣修改傳入的數(shù)據(jù),或者你可以拋出一個(gè)錯(cuò)誤:
const proxy = new Proxy({}, { set: (obj, prop, value) => { // Ensure age is of type Number if (prop === "age" && isNaN(value)) { throw new Error("Invalid age value!"); return; } obj[prop] = value; } }); proxy.age = "yes"; // Uncaught error: Invalid age value!
調(diào)試
你甚至可以使用Proxy來(lái)為自己提供調(diào)試點(diǎn)或事件,以查看如何以及何時(shí)設(shè)置和獲取值:
const proxy = new Proxy({}, { set: (obj, prop, value) => { console.log(`Setting ${prop} from ${obj[prop]} to ${value}`); obj[prop] = value; } }); proxy.prop = 1; proxy.prop = 2; // Setting prop from undefined to 1 // Setting prop from 1 to 2
即使您不修改任何輸入或輸出,擁有一個(gè)對(duì)象上值更改的掛鉤也是非常有價(jià)值的。
格式化
另一個(gè)簡(jiǎn)單的用法是格式化進(jìn)入對(duì)象的數(shù)據(jù):
const proxy = new Proxy({}, { set: (obj, prop, value) => { if (prop === "age") { obj[prop] = Number(value); } } }); proxy.prop = "1"; // 1
您可以格式化字符串到數(shù)字,數(shù)字到字符串,或簡(jiǎn)單地設(shè)置默認(rèn)值。
使用現(xiàn)有對(duì)象的代理
在上面的例子中,我們使用了空對(duì)象({}),但你也可以使用現(xiàn)有的對(duì)象:
const myObj = { x: "x", y: "y" }; // Use existing object, simply set value as is given const proxy = new Proxy(myObj, { set: (obj, prop, value) => { obj[prop] = value; } }); // proxy.x = "XXX"; proxy.x; // "XXX" myObj.x; // "XXX"
請(qǐng)注意,原始對(duì)象和代理都會(huì)發(fā)生變化,因此代理不能充當(dāng)“副本”。
人們討厭PHP,但我喜歡這門(mén)語(yǔ)言的一點(diǎn)是你可以監(jiān)視和動(dòng)態(tài)響應(yīng)的“魔法屬性”。代理API感覺(jué)像是JavaScript對(duì)這個(gè)問(wèn)題的回答。你能控制的東西越多,你的應(yīng)用就會(huì)變得越好!
作者介紹
熱門(mén)博客推薦