JavaScript代理Proxy的驚人力量

2021-12-26 大遷世界
今天我們要學習的是ECMAScript 6 Proxy。我們將在本文中涉及以下主題。

什麼是代理

代理人在行動

誰使用代理

使用案例和實例

資源簡介

開始吧:)

什麼是代理

正如MDN網站上所說。

Proxy對象可以讓你為另一個對象創建一個代理,它可以攔截和重新定義該對象的基本操作。

在解釋什麼是Proxy的時候,說它可以創建一個Proxy,這有點搞笑。當然,他們並沒有說錯,但是我們可以簡化這個說法,讓它更加友好。

Proxy對象使你能夠包裝目標對象 通過這樣可以攔截和重新定義該對象的基本操作。

基本上,它的意思是說,我們要把一個對象,用Proxy包裹起來,這將允許我們創建一個 "隱藏 "的門,並控制所有對所需對象的訪問。

一個小插曲,Proxy也是一種軟體設計模式,你一定要讀一讀(維基百科連結)。

一個Proxy的創建有兩個參數。

代碼

const target = {

message1: "hello",

message2: "everyone"

};

const handler = {};

const proxy = new Proxy(target, handler);

大多數瀏覽器都支持代理功能,但也有一些老的瀏覽器不支持(當然是IE),你可以在這裡查看完整的列表。google有一個代理的polyfill,但它不支持所有的代理功能。

現在知道了什麼是Proxies,想看看能用它做什麼。

代理人在行動

讓我們想像一下,我們是一家銀行或一個憂心忡忡的女朋友。我們想知道每次銀行帳戶餘額被訪問和被通知的時間。我們將使用最簡單的處理程序操作/trap: get

const bankAccount = {

balance: 2020,

name: 'Georgy Glezer'

};

const handler = {

get: function(target, prop, receiver) {

if (prop === 'balance') {

console.log(`Current Balance Of: ${target.name} Is: ${target.balance} `);

}

return target[prop];

}

};

const wrappedBankAcount = new Proxy(bankAccount, handler);

wrappedBankAcount.balance; // access to the balance

// OUTPUT:

// Current Balance Of: Georgy Glezer Is: 2020

// 2020

在上面的例子中,我們有一個銀行帳戶對象,裡面有我的名字和2020的餘額。

這次的處理者對象是實現get操作/trap,它接收一個有3個參數的函數和get的返回值。

我們定義了一個條件,如果被訪問的屬性是 "餘額",我們將通知(log)餘額和當前用戶名,並返回 "餘額 "屬性。

從輸出中可以看到,一旦 "balance "屬性被訪問,我們就通過使用Proxy和設置get操作/陷阱,很容易地通知(log)了這次訪問。

繼續我們銀行的想法,要求每次有人從銀行帳戶中取錢,我們都要得到通知。而另一個約束條件是,銀行不允許出現負餘額。為了達到這個目的,我們這次要使用設置處理程序/陷阱。

const bankAccount = {

balance: 2020,

name: 'Georgy Glezer'

};

const handler = {

set: function (obj, prop, value) {

console.log(`Current Balance: ${obj.balance}, New Balance: ${value}`);

if (value < 0) {

console.log(`We don't allow Negative Balance!`);

return false;

}

obj[prop] = value;

return true;

}

};

const wrappedBankAcount = new Proxy(bankAccount, handler);

wrappedBankAcount.balance -= 2000; // access to the balance

console.log(wrappedBankAcount.balance);

wrappedBankAcount.balance -= 50; // access to the balance

console.log(wrappedBankAcount.balance);

// OUTPUT:

// Current Balance: 2020, New Balance: 20

// 20

// Current Balance: 20, New Balance: -30

// We don't allow Negative Balance!

// 20

在上面的例子中,我們通知當前的餘額和取款後的新餘額,如果新的餘額是負數,我們也會通知並中止取款操作。

我們使用的是set operator/trap,它是一個返回布爾值(true/false)的函數,用來判斷更新操作是否成功。它接收以下參數。

你可以看到,它和get真的很相似,但只是多接收了1個新值的參數。

這2個操作符/陷阱是最常見的,如果你有興趣找到所有現有的操作符/陷阱,你可以在這裡查看。

誰使用代理

許多流行的庫都使用了這種技術,例如。

還有更多.他們中的大多數人都利用了Proxies給我們帶來的驚人力量,並為我們提供了很棒的庫。

使用案例和實例

我們已經看到,我們可以使用代理伺服器來進行。

緩存

我們將再次使用get operator/trap,並將 "dollars "屬性添加到我們的對象中。在每次訪問 "dollars "屬性時,我們將計算我們的餘額價值多少美元。因為計算可能是一個沉重的操作,我們希望儘可能多的Cache它。

const bankAccount = {

balance: 10,

name: 'Georgy Glezer',

get dollars() {

console.log('Calculating Dollars');

return this.balance *3.43008459;

}

};

let cache = {

currentBalance: null,

currentValue: null

};

const handler = {

get: function (obj, prop) {

if (prop === 'dollars') {

let value = cache.currentBalance !== obj.balance ? obj[prop] : cache.currentValue;

cache.currentValue = value;

cache.currentBalance = obj.balance;

return value;

}

return obj[prop];

}

};

const wrappedBankAcount = new Proxy(bankAccount, handler);

console.log(wrappedBankAcount.dollars);

console.log(wrappedBankAcount.dollars);

console.log(wrappedBankAcount.dollars);

console.log(wrappedBankAcount.dollars);

// OUTPUT:

// Calculating Dollars

// 34.3008459

// 34.3008459

// 34.3008459

// 34.3008459

正如你在例子中所看到的,我們有一個緩存對象,它保存著當前的銀行餘額和以美元為單位的餘額價值。每次有人訪問 "dollar "屬性時,我們都會先進行計算,然後將其緩存起來。

Dom操作

我們想在每次餘額發生變化時更新屏幕上的文字。我們將使用一個set操作符/trap,每次改變數值時,我們將更新屏幕上的DOM元素。

const bankAccount = {

balance: 2020,

name: "Georgy Glezer",

get text() {

return `${this.name} Balance Is: ${this.balance}`;

}

};

const objectWithDom = (object, domId) => {

const handler = {

set: function (obj, prop, value) {

obj[prop] = value;

document.getElementById(domId).innerHTML = obj.text;

return true;

}

};

return new Proxy(object, handler);

};

// create a dom element with id: bank-account

const wrappedBankAccount = objectWithDom(bankAccount, "bank-account");

wrappedBankAccount.balance = 26;

wrappedBankAccount.balance = 100000;

在這裡,我們創建了一個輔助函數,這樣我們就可以存儲DOM元素的ID,並在set operator/trap中添加了簡單的行來更新DOM元素。很簡單,對吧?讓我們看看結果:)

概要

綜上所述,我們了解了ECMAScript 6 Proxies,我們如何使用它們,以及用於什麼目的。在我看來,代理是一個神奇的工具,你可以用它來做各種各樣的選擇,你只需要考慮什麼是最適合你的:) 。

資源

關於本文譯者:飄飄作者:@Georgy Glezer原文:https://levelup.gitconnected.com/the-amazing-power-of-javascript-proxies-aa27c6d06bcb

來個【分享、點讚、在看】三連支持一下吧

css特效第一季:https://blog.csdn.net/qq449245884/category_9873715.html
css特效第二季:https://blog.csdn.net/qq449245884/category_10212382.html
css特效第三季:https://blog.csdn.net/qq449245884/category_10791873.html

相關焦點

  • 你不知道的 Proxy
    閱讀完本文,你將了解以下內容:Proxy 對象與 Reflect 對象的相關知識;一、聊一聊代理在日常工作中,相信挺多小夥伴都用過 Web 調試代理工具,比如 Fiddler 或 Charles。通過使用 Web 調試代理工具,我們可以抓取 HTTP/HTTPS 協議請求,還可以手動修改請求參數和響應結果。
  • 你不知道的 Proxy:ES6 Proxy 可以做哪些有意思的事情?
    顧名思義,Proxy 的意思是代理,作用是為其他對象提供一種代理以控制對這個對象的訪問。本文會涉及到 Proxy 和 Reflect、Function、擴展運算符 等知識,主要以實踐為主,對語法不會進行詳細地講解,建議配合阮一峰的 ES6入門 中相關章節服用。
  • 拿 Proxy 可以做哪些有意思的事兒
    Proxy的語法創建一個 Proxy的實例需要傳入兩個參數target 要被代理的對象,可以是一個 object或者 functionhandlers對該代理對象的各種操作行為處理let target = {}let handlers = {} // do nothinglet proxy = new Proxy
  • Linux上使用tinyproxy快速搭建HTTP/HTTPS代理器
    前言本文主要講解如何在Linux上使用tinyproxy搭建HTTP/HTTPS代理器。tinyproxy是一個HTTP/HTTPS代理。它是輕量級的、快速的、非常容易配置的,而且是一個開源的代理服務。Tinyproxy也可以配置為反向代理。它很適合用作具有較少系統資源的小型代理,因為它是非常輕量級的。
  • ES6 Proxy 可以做哪些有意思的事情?
    顧名思義,Proxy 的意思是代理,作用是為其他對象提供一種代理以控制對這個對象的訪問。本文會涉及到 Proxy 和 Reflect、Function、擴展運算符 等知識,主要以實踐為主,對語法不會進行詳細地講解,建議配合阮一峰的 ES6入門 中相關章節服用。
  • 反向代理與 Real-IP 和 X-Forwarded-For
    NginxProxy 1,通過「proxy_set_header X-Real-IP $remote_addr」把真實客戶端IP寫入到請求頭X-Real-IP,在NginxBackend輸出$http_x_real_ip獲取到了真實客戶端IP;而Nginx Backend的「$remote_addr」輸出為最後一個反向代理的IP;「proxy_set_headerX-Forwarded-For
  • 代理伺服器有哪幾種 如何獲取代理伺服器【詳細介紹】
    4、啟動代理獵手,選擇「導入結果」,找到剛才編輯的proxy.txt文件,導入即可(記住要選中「避免導入重複項」)。  5、選中剛才導入的結果,點擊〔檢驗〕,能不能用就清楚了。  更重要的是:Proxy Server(代理伺服器)是Internet鏈路級網關所提供的一種重要的安全功能,它的工作主要在開放系統互聯(OSI)模型的對話層。  proxy對於我們這麼有用,那麼究竟怎樣才可以在偌大的網絡上找尋這些伺服器呢?
  • ShadowsocksR隧道代理繞過GFW
    export http_proxy=http://127.0.0.1:8118export https_proxy=https://127.0.0.1:8118Chrome SwitchyOmega:Github: https://github.com/FelisCatus/SwitchyOmega/releasesWebsite
  • 「原創」讓設計模式飛一會兒|⑥面試必問代理模式
    proxyClassCache是一個定義在Proxy中的欄位,你就將其當做一個代理類的緩存。這個也好理解,稍後大家會看到,動態代理類生成過程中會伴隨大量的IO操作,字節碼操作還有反射操作,還是比較消耗資源的。如果需要創建的代理類數量特別多,性能會比較差。所以Proxy提供了緩存機制,將已經生成的代理類緩存,當獲取時,會先從緩存獲取,如果獲取不到再執行生成邏輯。
  • 利用 Charles Proxy 下載舊版本 iOS App
    請點擊 Grant Privilege 並輸入管理員密碼,這將自動為系統配置代理設置以啟用 Charles 服務。(如果你配置過 Surge MitM 那你已經很熟悉了)接下來我們需要先處理證書的問題:注意 這步非常重要 如果你使用 iTunes 12 或以上版本 此步失敗將導致 iTunes不驗證 SSL 伺服器身份阻止你下載Windows 通過證書方法請參照英語官網方法 https://www.charlesproxy.com/documentation/using-charles
  • JavaScript:學會toString()字符串
    javascript中的toString()方法,主要用於Array、Boolean、Date、Error、Function
  • 第一篇:JavaScript基本語法
    html><head><title>這是登錄頁面</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><script type="text/javascript
  • JavaScript模擬輪播圖效果
    div{       border: 1px solid white;       width:600px ;       height:400px;       margin: auto;       text-align: center;     }   </style>   <script type="text/javascript
  • JavaScript函數 - 遞歸
    >2.找出一個臨界值,n==0時,就不需要列印了,直接return;即可3.不等於0時,直接document.write列印hello world4.然後緊跟著return print(n-1); 依次列印<script type = "text/javascript
  • 精讀《高性能 javascript》
    前言本期我來給大家推薦的書是《高性能JavaScript》,在這本書中我們能夠了解 javascript 開發過程中的性能瓶頸,如何提升各方面的性能
  • (14/30)Blazor系列:JavaScript interop(互操作)
    https://sweetalert.js.org[2]Blazor版本: https://github.com/Basaingeal/Razor.SweetAlert2[3]Blazor JavaScript interoperability (JS interop): https://docs.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability
  • 20個常用的JavaScript簡寫技巧
    箭頭函數 參考:JavaScript Arrow function https://jscurious.com/javascript-arrow-function/ 8. 模板字符串 我們一般使用 + 運算符來連接字符串變量。