WeHelp
JavaScript Proxy 代理物件基礎介紹
2023-02-17 04:29:18
近幾年,JavaScript 程式語言持續的演進,提供了許多新的程式開發工具和技巧。其中,定義在 JavaScript ES6 規格中的 Proxy 代理物件,提供我們「代理」某個目標物件的包裝工具。所謂的「代理」,意思是改變、或中介該目標物件的基本操作行為,例如取得物件屬性、或者是利用指定運算設定物件屬性這樣的基本操作。 以下,我們用一個入門範例,來幫助大家快速的入門 Proxy 代理物件的基礎運作觀念。 --- ### 簡單的需求 我們有一個物件,存放使用者購買商品的單價和數量: ``` javascript let data={ price:100, count:5 }; ``` 如果需要總價的資訊,我們不會特別紀錄在物件屬性中,因為總價是依賴單價和數量決定,並非獨立的資料。所以,透過一個簡單的運算完成,並且印出來: ``` javascript console.log(data.price*data.count); // 印出 500 ``` 是否能把這樣的運算用函式包裝,未來需要做總價的計算時,可以用更簡短的程式碼來進行呢?可以的: ``` javascript let data={ price:100, count:5, getTotal:function(){ return this.price*this.count; } } console.log(data.getTotal()); // 印出 500 ``` 那麼,是否有其他的包裝方式呢?有的,Proxy 代理物件提供了另外一種包裝程式碼的可能性,將目標物件的屬性經過額外的組合運算後,得到最終我們想要的資料。 --- ### 運用代理物件,改變取得物件屬性的行為 Proxy 代理物件的使用流程如下: 1. 建立任意的目標物件。 2. 建立一個包含取得物件屬性的處理函式物件。 3. 使用 Proxy 的建構式,建立代理物件。 4. 使用代理物件來取得屬性的資料。 Proxy 代理物件的建構式語法如下: ``` javascript new Proxy(要代理的目標物件, 包含處理函式的物件); ``` 最終,我們用以下程式完成一次代理物件的基礎運用:將目標物件紀錄的單價和數量相乘,得到總價的資訊並印出來: ``` javascript // 建立任意的目標物件 let data={ price:100, count:5 }; // 建立包含取得物件屬性的處理函式物件 let handlers={ // 名為 get 的函式,會在代理物件試圖取得屬性資料時被呼叫 get:function(target, property){ // 第一個參數代表一開始設定的目標物件,第二個參數代表要取得的屬性名稱 if(property==="total"){ // 如果要取得的屬性是 total,特別根據目標物件的單價和數量,計算後回傳 return target.price*target.count; }else{ // 如果要取得其他的屬性,則回傳目標物件本來的資料 return target[property]; } } }; // 建立目標物件的代理物件,改變取得物件屬性的行為 let dataProxy=new Proxy(data, handlers); // 取得代理物件的屬性,實際上會呼叫上述的 get 函式,並取得回傳值 console.log(dataProxy.total); // 使用 total 屬性取得總價的資料 console.log(dataProxy.price); // 根據 get 函式的內部邏輯,會取得原始目標物件的單價資料 ``` --- ### Proxy 使用目的、更多的運用方式 如上所展示的,雖然我們在建立代理物件的步驟中,多寫了很多程式碼,但最終的使用方式可說是精簡到不能再精簡,僅僅利用一個 `dataProxy.total` 就表達了背後根據基礎屬性進行的運算邏輯,並取得計算的結果。一旦我們要包裝的程式邏輯越來越複雜的時候,Proxy 代理物件的機制,就更能發揮它的優勢。 另外,Proxy 代理物件能夠中介的操作也不只是單純的取得物件屬性 (get),還可以中介設定物件屬性 (set)、檢查屬性名稱 (has)、甚至建構函式的呼叫 (construct) 等等動作。若能完整的運用 Proxy 代理物件的特性,我們至少可以提供以下用途: 1. 取得經過運算後的屬性資料。 2. 驗證準備存放進物件屬性的資料。 3. 修正或補足物件屬性潛在的資料錯誤或缺漏。 4. 綁定物件屬性和網頁的畫面。 當然,我們還需要學習更多代理物件的細節,才能夠做到以上的各種用途。本文就暫且不表,留到往後再繼續吧 ~