JavaScript ES6代理的實際用例,快速教你用好ES6代理

来源:https://www.cnblogs.com/coderhf/archive/2020/07/02/13225358.html
-Advertisement-
Play Games

元編程是一種強大的技術,使你能夠編寫可以創建其他程式的程式。ES6藉助代理和許多類似功能,使在JavaScript中利用元編程變得更加容易。ES6 Proxy(代理) 有助於重新定義對象的基本操作,從而為各種可能性打開了大門。 本指南可以幫助您理解為什麼ES6代理如此之好,尤其是對於元編程而言: 什 ...


元編程是一種強大的技術,使你能夠編寫可以創建其他程式的程式。ES6藉助代理和許多類似功能,使在JavaScript中利用元編程變得更加容易。ES6 Proxy(代理) 有助於重新定義對象的基本操作,從而為各種可能性打開了大門。

本指南可以幫助您理解為什麼ES6代理如此之好,尤其是對於元編程而言:

  • 什麼是ES6代理

  • 如何以及何時實施代理

  • 如何使用ES6代理執行訪問控制,數據綁定和緩存

  • ES6代理不是性能密集型任務的理想選擇

先決條件和結果

本教程主要針對有JavaScript經驗的開發人員,至少要熟悉ES6代理的概念。如果你已經對代理作為一種設計模式有了牢固的理解,那麼這些知識應該可以轉化為現實。

閱讀本指南後,你應該能夠:

  • 瞭解什麼是ES6代理,如何實現以及何時使用它

  • 使用ES6代理進行訪問控制,緩存和數據綁定

ES6代理剖析:目標(Target),處理程式(handler)和陷阱(trap)

從根本上來說,代理是指某件事或某人成為其他事物的替代品,所以不管是什麼東西,都要經過替代品才能達到真正的交易。ES6代理的工作原理也是如此。

為了有效地實現和使用ES6代理,你必須瞭解三個關鍵術語:

  1. Target——代理人所替代的真正的交易,目標是站在代理背後的東西。這可以是任何對象。

  2. Handler——一個包含所有代理的陷阱邏輯的對象。

  3. Trap——與操作系統中的陷阱類似,此上下文中的陷阱是以某種方式提供對對象的訪問的方法(可理解為攔截行為)。

綜上所述,下麵是最簡單的實現,如果使用ES6代理,對象中不存在給定的屬性,則可以返回不同的內容。

 const target = {
   someProp: 1
 }
 ​
 const handler = {
   get: function(target, key) {
     return key in target ? 
       target[key] : 
     'Doesn't exist!';
   }
 }
 ​
 const proxy = new Proxy(target, handler);
 console.log(proxy.someProp) // 1
 console.log(proxy.someOtherProp) // Doesn't exist!

 

ES6代理是一項強大的功能,可促進JavaScript中對象的虛擬化。

數據綁定:同步多個對象

由於數據綁定的複雜性,它通常很難實現。ES6代理實現雙向數據綁定的應用可以在JavaScript的MVC庫中看到,在這些庫中,當DOM發生變化時,對象會被修改。

簡而言之,數據綁定是一種將多個數據源綁定在一起以使其同步的技術。

假設存在一個名為 username 的 ``。

 <input type="text" id="username" /> 

假設你要使此輸入的值與對象的屬性保持同步。

 const inputState = {
   id: 'username',
   value: ''
 }

 

當輸入的值發生變化時,通過監聽輸入的變化事件,然後更新 inputState 的值,修改 inputState 是相當容易的。然而,反過來,在 inputState 被修改時更新輸入,則相當困難。

ES6代理可以在這種情況下提供幫助。

 const input = document.querySelector('#username')
 const handler = {
   set: function(target, key, value) {
     if (target.id && key === 'username') {
       target[key] = value;
       document.querySelector(`#${target.id}`)
         .value = value;
       return true
     }
     return false
   }
 }
 ​
 const proxy = new Proxy(inputState, handler)
 proxy.value = 'John Doe'
 console.log(proxy.value, input.value) 
 // 雙方都將印有“ John Doe”

 

這樣,當 inputState 更改時,input 將反映已進行的更改。結合偵聽 change 事件,這將生成 inputinputState 的簡單雙向數據綁定。

雖然這是一個有效的用例,但通常不建議這樣做。以後再說。

緩存:提高代碼性能

緩存是一個古老的概念,它允許非常複雜和大型的應用程式保持相對的性能。緩存是存儲某些數據的過程,以便在請求時可以更快地提供數據。緩存並不永久地存儲任何數據。緩存失效是保證緩存新鮮的過程。這是開發人員共同的苦惱。正如Phil Karlton所說:"電腦科學中只有兩件難事:緩存無效和給事物命名。"

ES6代理使緩存更加容易。例如,如果你要檢查對象中是否存在某些東西,它將首先檢查緩存並返回數據,或者如果不存在則進行其他操作以獲取該數據。

假設你需要進行很多API調用才能獲取特定信息並對其進行處理。

 const getScoreboad = (player) => {
   fetch('some-api-url')
     .then((scoreboard) => {
     // 用記分牌做點什麼
   })
 }

 

這就意味著,每當需要一個球員的記分牌時,就必須進行一次新的調用。相反,你可以在第一次請求時緩存記分牌,隨後的請求可以從緩存中獲取。

 const cache = { 
   'John': ['55', '99']
 }
 const handler = { 
   get: function(target, player) {
     if(target[player] {
        return target[player]
   } else {
     fetch('some-api-url')
       .then(scoreboard => {
         target[player] = scoreboard
         return scoreboard
       })
     }
   }
 }
 const proxy = new Proxy(cache, handler)
 // 訪問緩存並使用記分牌做一些事情

 

這樣,僅當緩存中不包含玩家的記分牌時,才會進行API調用。

訪問控制:控制進出對象的內容

最簡單的用例是訪問控制,ES6代理的大部分內容都屬於訪問控制。

讓我們探索使用E6代理的訪問控制的一些實際應用。

1. 驗證

ES6代理最直觀的用例之一是驗證對象內部的內容,以確保對象中的數據儘可能準確。例如,如果你想強制執行產品描述的最大字元數,可以這樣做。

 const productDescs = {}
 const handler = {
   set: function(target, key, value) {
     if(value.length > 150) {
       value = value.substring(0, 150)
     }
     target[key] = value
   }
 }
 const proxy = new Proxy(productDescs, handler)

 

現在,即使你添加的描述超過150個字元,也會被刪減並添加。

2. 提供對象的只讀視圖

有時候你可能要確保不以任何方式修改對象,並且只能將其用於讀取目的。 JavaScript提供了 Object.freeze() 來執行此操作,但是使用代理時,該行為更可自定義。

 const importantData = {
   name: 'John Doe',
   age: 42
 }
 ​
 const handler = {
   set: 'Read-Only',
   defineProperty: 'Read-Only',
   deleteProperty: 'Read-Only',
   preventExtensions: 'Read-Only',
   setPrototypeOf: 'Read-Only'
 }
 ​
 const proxy = new Proxy(importantData, handler)

 

現在,當你嘗試以任何方式更改對象時,你只會收到一個字元串,表示只讀。否則,你可能會引發錯誤以指示該對象是只讀的。

3. 私有屬性

JavaScript本身並沒有私有屬性,除了閉包。當 Symbol 數據類型被引入時,它被用來模仿私有屬性。但隨著Object.getOwnPropertySymbols 方法的引入,它被拋棄了。ES6代理並不是一個完美的解決方案,但在緊要關頭它們可以完成任務。

一種常見的約定是通過在名稱前加上下劃線來標識私有屬性,這個約定允許你使用ES6代理。

 const object = {
   _privateProp: 42
 }
 ​
 const handler = {
   has: function(target, key) {
     return !(key.startsWith('_') && key in target)
   },
   get: function(target, key, receiver) {
     return key in receiver ? target[key] : undefined
   }
 }
 ​
 const proxy = new Proxy(object, handler)
 proxy._privateProp // undefined

 

添加 ownKeysdeleteProperty 會讓這個實現更接近於真正的私有屬性。然後,你仍然可以在開發者控制臺中查看代理對象。如果你的用例與上面的實現一致,它仍然適用。

為何以及何時使用代理

ES6代理並不是性能密集型任務的理想選擇。這就是為什麼進行必要的測試是至關重要的。代理可以在任何預期對象的地方使用,代理只需幾行代碼就能提供複雜的功能,這使它成為元編程的理想功能。

代理通常與另一個稱為Reflect的元編程功能一起使用。

總結

對了,小編為大家準備了一套2020最新的web前端資料,需要點擊下方鏈接獲取方式

學習前端,你掌握這些。二線也能輕鬆拿8K以上

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 最近做一個簡單的應用,使用到了一些WebView的相關知識,這裡做一些總結。 為WebView中的輸入框賦值 讀取WebView控制項中的值 執行WebView中網頁的方法 註入一段js代碼,為一個控制項賦值一個點擊方法 讀取WebView網頁中的表格. 一、為輸入框賦值和取值 首先,載入網頁的方 ...
  • 前端開發當中最有意思的就是實現動畫特效,Flutter提供的各種動畫組件可以方便實現各種動畫效果。Flutter中的動畫組件主要分為兩類: 隱式動畫控制項:只需設置組件開始值,結束值,執行時間,比如AnimatedOpacity,AnimatedSize等組件。 顯式動畫控制項:需要設置Animatio ...
  • break語句描述:break語句,用於無條件結束各種迴圈(退出迴圈)和switch。說明:一般情況下,需要在break語句之前加一個條件判斷。換句話說:就是條件成立了,就退出迴圈。continue語句描述:結束本次迴圈,而開始下一次迴圈。continue之後的代碼不再執行了。說明:一般情況下,需要 ...
  • if條件判斷語句:條件成立,執行什麼代碼;條件不成立,執行什麼代碼結構一:只判斷真(true),條件為假,什麼也不做if(條件判斷:判斷結果是一個布爾值){條件為真(true),執行的代碼} 結構二:既判斷真,也判斷假 if(條件判斷){條件為真,執行的代碼}else{條件為假,執行的代碼} 結構三 ...
  • Koch曲線的構造過程是:取一條長度為L0的直線段,將其三等分,保留兩端的線段,將中間的一段改換成夾角為60度的兩個等長直線;再將長度為L0/3的4個直線段分別進行三等分,並將它們中間的一段均改換成夾角為60度的兩段長為L0/9的直線段;重覆以上操作直至無窮,可得以一條具有自相似結構的折線,如圖1所 ...
  • 1 問題 當使用pdfjs來實現預覽功能的時候,遇到了2個問題: 一是帶寬占用過大,會下載整個pdf文件,這對部署在公網的應用來說,成本壓力很大,因為雲服務帶寬是很貴的。 二是記憶體占用過大,一個80M的pdf,在預覽時占用記憶體高達600M,在一些記憶體較小的手機上容易發生崩潰。 pdfjs預設配置下, ...
  • 1.圖片標簽 img src:圖片路徑 width:設置圖片的寬度,如果是單獨設置,則保存圖片比例進行修改,單位可以是px和% height:設置圖片的高度,如果是單獨設置,則保存圖片比例進行修改,單位可以是px和% title:滑鼠放在圖片上提示圖片名稱 alt:當圖片路徑有誤的時候用來提示 路徑 ...
  • 關於HTML中的 <!DOCTYPE> 聲明 今天在完成課程任務時,我的HTML代碼中一處出現了一個問題。 我現在有三張圖片,這三張圖片是從一張圖片無縫裁剪下來的,這三張圖片均等寬不等高,若使用PS可完美拼接回原圖。我在表格內,將此三張圖片放入,當瀏覽器運行時,我發現此三圖片並未完美緊密貼合,而是兩 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...