摘要:此方法充當(dāng)攔截器,在返回值之前,會首先對屬性值進(jìn)行檢查,如果不存在,則拋出異常。輸出與第一種情況相同,但此時(shí)函數(shù)專注于邏輯,只處理消息。在這種情況下,我們需要使用方法,并在其中進(jìn)行驗(yàn)證。在此示例中,我們不允許空和發(fā)布請求而不提供數(shù)據(jù)。
翻譯:劉小夕什么是 Proxy原文鏈接:https://devinduct.com/blogpos...
通常,當(dāng)談到JavaScript語言時(shí),我們討論的是ES6標(biāo)準(zhǔn)提供的新特性,本文也不例外。 我們將討論JavaScript代理以及它們的作用,但在我們深入研究之前,我們先來看一下Proxy的定義是什么。
MDN上的定義是:代理對象是用于定義基本操作的自定義行為(例如,屬性查找,賦值,枚舉,函數(shù)調(diào)用等)。
換句話說,我們可以說代理對象是我們的目標(biāo)對象的包裝器,我們可以在其中操縱其屬性并阻止對它的直接訪問。 你可能會發(fā)現(xiàn)將它們應(yīng)用到實(shí)際代碼中很困難,我鼓勵(lì)你仔細(xì)閱讀這個(gè)概念,它可能會改變你的觀點(diǎn)。
術(shù)語handler
包含陷阱(traps)的占位符對象。
traps
提供屬性訪問的方法。這類似于操作系統(tǒng)中捕獲器的概念。
target
代理虛擬化的對象。(由代理對象包裝和操作的實(shí)際對象)
在本文中,我將為 get 和 set 陷阱 提供簡單的用例,考慮到最后,我們將看到如何使用它們并包含更復(fù)雜的功能,如API。
語法和用例let p = new Proxy(target, handler);
將目標(biāo)和處理程序傳遞給Proxy構(gòu)造函數(shù),這樣就創(chuàng)建了一個(gè)proxy對象?,F(xiàn)在,讓我們看看如何利用它。為了更清楚地看出Proxy的好處,首先,我們需要編寫一些沒有它的代碼。
想象一下,我們有一個(gè)帶有幾個(gè)屬性的用戶對象,如果屬性存在,我們想要打印用戶信息,如果不存在,則拋出異常。在不使用代理對象時(shí),判斷屬性值是否存在的代碼也放在了打印用戶信息的函數(shù),即 printUser 中(這并不是我們所希望的),如下demo所示:
let user = { name: "John", surname: "Doe" }; let printUser = (property) => { let value = user[property]; if (!value) { throw new Error(`The property [${property}] does not exist`); } else { console.log(`The user ${property} is ${value}`); } } printUser("name"); // 輸出: "The user name is John" printUser("email"); // 拋出錯(cuò)誤: The property [email] does not existget
通過查看上面的代碼,你會發(fā)現(xiàn):將條件和異常移到其他地方,而printUser中僅關(guān)注顯示用戶信息的實(shí)際邏輯會更好。這是我們可以使用代理對象的地方,讓我們更新一下這個(gè)例子。
let user = { name: "John", surname: "Doe" }; let proxy = new Proxy(user, { get(target, property) { let value = target[property]; if (!value) { throw new Error(`The property [${property}] does not exist`); } return value; } }); let printUser = (property) => { console.log(`The user ${property} is ${proxy[property]}`); }; printUser("name"); // 輸出: "The user name is John" printUser("email"); // 拋出錯(cuò)誤: The property [email] does not exist
在上面的示例中,我們包裝了 user 對象,并設(shè)置了一個(gè) get 方法。 此方法充當(dāng)攔截器,在返回值之前,會首先對屬性值進(jìn)行檢查,如果不存在,則拋出異常。
輸出與第一種情況相同,但此時(shí) printUser 函數(shù)專注于邏輯,只處理消息。
set代理可能有用的另一個(gè)例子是屬性值驗(yàn)證。在這種情況下,我們需要使用 set 方法,并在其中進(jìn)行驗(yàn)證。例如,當(dāng)我們需要確保目標(biāo)類型時(shí),這是一個(gè)非常有用的鉤子。我們來看一下實(shí)際使用:
let user = new Proxy({}, { set(target, property, value) { if (property === "name" && Object.prototype.toString.call(value) !== "[object String]") { // 確保是 string 類型 throw new Error(`The value for [${property}] must be a string`); }; target[property] = value; } }); user.name = 1; // 拋出錯(cuò)誤: The value for [name] must be a string
這些是相當(dāng)簡單的用例,以下場景,proxy均可以派上用場:
格式化
價(jià)值和類型修正
數(shù)據(jù)綁定
調(diào)試
...
現(xiàn)在是時(shí)候創(chuàng)建一個(gè)更復(fù)雜的用例了。
具有代理的API - 更復(fù)雜的示例通過使用簡單用例中的知識,我們可以創(chuàng)建一個(gè)API包裝器,以便在我們的應(yīng)用程序中使用。 當(dāng)前只支持 get 和 post 請求,但它可以很容易地?cái)U(kuò)展。代碼如下所示。
const api = new Proxy({}, { get(target, key, context) { return target[key] || ["get", "post"].reduce((acc, key) => { acc[key] = (config, data) => { if (!config && !config.url || config.url === "") throw new Error("Url cannot be empty."); let isPost = key === "post"; if (isPost && !data) throw new Error("Please provide data in JSON format when using POST request."); config.headers = isPost ? Object.assign(config.headers || {}, { "content-type": "application/json;chartset=utf8" }) : config.headers; return new Promise((resolve, reject) => { let xhr = new XMLHttpRequest(); xhr.open(key, config.url); if (config.headers) { Object.keys(config.headers).forEach((header) => { xhr.setRequestHeader(header, config.headers[header]); }); } xhr.onload = () => (xhr.status === 200 ? resolve : reject)(xhr); xhr.onerror = () => reject(xhr); xhr.send(isPost ? JSON.stringify(data) : null); }); }; return acc; }, target)[key]; }, set() { throw new Error("API methods are readonly"); }, deleteProperty() { throw new Error("API methods cannot be deleted!"); } });
讓我們解釋一下簡單實(shí)現(xiàn),set 和 deleteProperty。 我們添加了一個(gè)保護(hù)級別,并確保每當(dāng)有人意外或無意地嘗試為任何API屬性設(shè)置新值時(shí),都會拋出異常。
每次嘗試刪除屬性時(shí)都會調(diào)用 deleteProperty 方法??梢源_保沒有人可以從我們的代理(即此處的 api)中刪除任何屬性,因?yàn)橥ǔN覀兌疾幌雭G失API方法。
get 在這里很有趣,它做了幾件事。target 是一個(gè)空對象,get 方法將在第一次有人使用 api 時(shí)創(chuàng)建所有方法(如當(dāng)前的 get 和 post請求),在 reduce 回調(diào)中,我們根據(jù)提供的配置執(zhí)行API規(guī)范所需的驗(yàn)證和檢查。在此示例中,我們不允許空URL和發(fā)布請求而不提供數(shù)據(jù)。這些檢查可以擴(kuò)展和修改,但重要的是我們只能在這一個(gè)地方集中處理。
reduce 僅在第一次API調(diào)用時(shí)完成,之后都會跳過整個(gè) reduce 進(jìn)程,get 只會執(zhí)行默認(rèn)行為并返回屬性值,即API處理程序。每個(gè)處理程序返回一個(gè)Promise對象,負(fù)責(zé)創(chuàng)建請求并調(diào)用服務(wù)。
使用:
api.get({ url: "my-url" }).then((xhr) => { alert("Success"); }, (xhr) => { alert("Fail"); });
delete api.get; //throw new Error("API methods cannot be deleted!");結(jié)論
當(dāng)您需要對數(shù)據(jù)進(jìn)行更多控制時(shí),代理可以派上用場。你可以根據(jù)受控規(guī)則擴(kuò)展或拒絕對原始數(shù)據(jù)的訪問,從而監(jiān)視對象并確保正確行為。
如果您喜歡這篇文章,請關(guān)注我的公眾號??梢栽谙旅娴脑u論部分中表達(dá)您的想法。
謝謝各位小伙伴愿意花費(fèi)寶貴的時(shí)間閱讀本文,如果本文給了您一點(diǎn)幫助或者是啟發(fā),請不要吝嗇你的贊和Star,您的肯定是我前進(jìn)的最大動力。https://github.com/YvetteLau/...
關(guān)注小姐姐的公眾號,加入交流群。文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/106442.html
摘要:協(xié)議轉(zhuǎn)換微服務(wù)架構(gòu)允許使用不同的協(xié)議以便于獲得使用不同技術(shù)的優(yōu)勢。過于龐大的在實(shí)現(xiàn)時(shí),應(yīng)當(dāng)避免將非通用邏輯如領(lǐng)域特定數(shù)據(jù)轉(zhuǎn)換放入其中。服務(wù)應(yīng)始終對其數(shù)據(jù)域擁有完全的所有權(quán)。構(gòu)建一個(gè)過于龐大的,從服務(wù)團(tuán)隊(duì)爭奪控制權(quán),這違反了微服務(wù)的理念。 我們團(tuán)隊(duì)的后端服務(wù)中,一開始只有一個(gè)大服務(wù),所有的東西都往里面寫,可以想象下,當(dāng)這個(gè)服務(wù)變得不斷的龐大,將會變得多么難以維護(hù)。后來逐漸把一些數(shù)據(jù)服務(wù)抽...
摘要:在下文中,首先我會介紹的使用方式,然后列舉具體實(shí)例解釋的使用場景。如果簡單地區(qū)分和的使用場景,可以概括為的核心作用是控制外界對被代理者內(nèi)部的訪問,的核心作用是增強(qiáng)被裝飾者的功能。 文章永久鏈接地址:http://pinggod.com/2016/%E5%AE%9E%E4%BE%8B%E8%A7%A3%E6%9E%90-ES6-Proxy-%E4%BD%BF%E7%94%A8%E5%9C...
摘要:最全正則表達(dá)式總結(jié)驗(yàn)證號手機(jī)號中文郵編身份證地址等是正則表達(dá)式的縮寫,作用是對字符串執(zhí)行模式匹配。學(xué)習(xí)目標(biāo)了解正則表達(dá)式語法在中使用正則表達(dá)式在中使 JS高級技巧 本篇是看的《JS高級程序設(shè)計(jì)》第23章《高級技巧》做的讀書分享。本篇按照書里的思路根據(jù)自己的理解和經(jīng)驗(yàn),進(jìn)行擴(kuò)展延伸,同時(shí)指出書里的一些問題。將會討論安全的類型檢測、惰性載入函數(shù)、凍結(jié)對象、定時(shí)器等話題。1. 安全的類型檢測...
摘要:譯使用更好的封裝更多前端技術(shù)和知識點(diǎn),搜索訂閱號菌訂閱看到篇文章覺得不錯(cuò),原文。講的是使用來封裝,做一層提供存取數(shù)據(jù)的代理層。這里簡單翻譯一下這篇文章的主要內(nèi)容。請關(guān)注我的訂閱號,不定期推送有關(guān)的技術(shù)文章,只談技術(shù)不談八卦 showImg(https://segmentfault.com/img/remote/1460000019889841?w=640&h=426); [譯]使用 P...
閱讀 3415·2023-04-26 02:41
閱讀 2469·2023-04-26 00:14
閱讀 2884·2021-08-11 10:22
閱讀 1292·2019-12-27 11:38
閱讀 3582·2019-08-29 18:34
閱讀 2389·2019-08-29 12:13
閱讀 2962·2019-08-26 18:26
閱讀 1872·2019-08-26 16:49