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
  • 前言 插件化的需求主要源於對軟體架構靈活性的追求,特別是在開發大型、複雜或需要不斷更新的軟體系統時,插件化可以提高軟體系統的可擴展性、可定製性、隔離性、安全性、可維護性、模塊化、易於升級和更新以及支持第三方開發等方面的能力,從而滿足不斷變化的業務需求和技術挑戰。 一、插件化探索 在WPF中我們想要開 ...
  • 歡迎ReaLTaiizor是一個用戶友好的、以設計為中心的.NET WinForms項目控制項庫,包含廣泛的組件。您可以使用不同的主題選項對項目進行個性化設置,並自定義用戶控制項,以使您的應用程式更加專業。 項目地址:https://github.com/Taiizor/ReaLTaiizor 步驟1: ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • Channel 是乾什麼的 The System.Threading.Channels namespace provides a set of synchronization data structures for passing data between producers and consume ...
  • efcore如何優雅的實現按年分庫按月分表 介紹 本文ShardinfCore版本 本期主角: ShardingCore 一款ef-core下高性能、輕量級針對分表分庫讀寫分離的解決方案,具有零依賴、零學習成本、零業務代碼入侵適配 距離上次發文.net相關的已經有很久了,期間一直在從事java相關的 ...
  • 前言 Spacesniffer 是一個免費的文件掃描工具,通過使用樹狀圖可視化佈局,可以立即瞭解大文件夾的位置,幫助用戶處理找到這些文件夾 當前系統C盤空間 清理後系統C盤空間 下載 Spacesniffer 下載地址:https://spacesniffer.en.softonic.com/dow ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • 一、ReZero簡介 ReZero是一款.NET中間件 : 全網唯一開源界面操作就能生成API , 可以集成到任何.NET6+ API項目,無破壞性,也可讓非.NET用戶使用exe文件 免費開源:MIT最寬鬆協議 , 一直從事開源事業十年,一直堅持開源 1.1 純ReZero開發 適合.Net Co ...
  • 一:背景 1. 講故事 停了一個月沒有更新文章了,主要是忙於寫 C#內功修煉系列的PPT,現在基本上接近尾聲,可以回頭繼續更新這段時間分析dump的一些事故報告,有朋友微信上找到我,說他們的系統出現了大量的http超時,程式不響應處理了,讓我幫忙看下怎麼回事,dump也抓到了。 二:WinDbg分析 ...
  • 開始做項目管理了(本人3年java,來到這邊之後真沒想到...),天天開會溝通整理需求,他們講話的時候忙裡偷閑整理一下常用的方法,其實語言還是有共通性的,基本上看到方法名就大概能猜出來用法。出去打水的時候看到外面太陽好好,真想在外面坐著曬太陽,回來的時候好兄弟三年前送給我的鍵盤D鍵不靈了,在打"等待 ...