如何建立 JavaScript 裝飾器以及如何使用自動存取器來幫助改善開發者體驗的演練。
GitHub 上的裝飾器提案已經在分解裝飾器的基本用例方面做得很好。我的目標不是在那裡重新創建這些範例,而是突出一些鮮為人知的功能和互動。此外,在本系列的下一篇文章中,我將重點介紹如何在單一類別屬性上組合或連結多個裝飾器。
每個程式碼範例都將附帶一個互動式 Babel REPL 遊樂場的鏈接,因此您可以自己嘗試,而無需設定 polyfill 或啟動儲存庫。在我的所有範例中,應選取左上角(「設定」下)的「評估」選項,這意味著您將能夠查看程式碼、編輯它、開啟瀏覽器的開發控制台,並在那裡查看日誌/結果。
你不需要注意 Babel REPL 右側的轉譯代碼,除非你想深入研究裝飾器的 polyfill。 Babel REPL 的左側是您可以編輯和編寫程式碼親自嘗試的地方。
要強調的是,您的開發人員工具的控制台應該會顯示控制台日誌。如果沒有,請確保在左上角選中“評估”。
裝飾器規格的一個重要功能是自動存取器。我們將從學習它們是什麼以及使用自動存取器如何使編寫裝飾器變得更容易開始。
裝飾者提案在這裡概述了自動訪問器。但最終它只是一個簡單的功能;讓我們來看一個基本的工作範例:Babel REPL。
class MyClass { accessor myBoolean = false }
在此類定義中,存取器關鍵字位於屬性名稱之前。然而,這並沒有真正改變屬性的任何內容 - 接下來,我們將看到自動存取器與裝飾器結合使用時有多麼有用。
(請注意,您也可以將 static 與自動存取器一起使用,例如靜態存取器 myBoolean = false)
為了更好地理解為什麼我們使用自動訪問器,讓我們建造一些裝飾器。
我們先將自動存取器與實際上作用不大的裝飾器結合起來,以便了解語法。
這是一個保留內部變數的函數裝飾器,並允許您透過類別上的屬性來取得和設定該變數:Babel REPL
function simpleDecorator(value, context) { let internalValue = false return { get() { return internalValue }, set(val) { internalValue = val return internalValue } } } class MyClass { @simpleDecorator accessor myBoolean }
這個裝飾器回傳一個有兩個方法的物件:get() 和 set()。這就是自動存取器的裝飾器如何「裝飾」或將屬性的 setter 和 getter 包裝在一個地方;我們不必創建 simpleGetterDecorator 和 simpleSetterDecorator。相反,我們使用自動存取器將它們組合成一個定義,這更容易。
最後,到目前為止,這看起來是一個相當正常的函數 - 這非常適合介紹!
為了讓我們為本文的其餘部分做好準備,讓我們更新我們的裝飾器,以便它實際上進行某種驗證。我們將製作一個裝飾器,它只允許您設定偶數,而不允許設定其他數字。看起來是這樣:Babel REPL
function onlyEvenNumbers(value, context) { let internalNumber = 0 return { get() { return internalNumber }, set(val) { const num = Number(val) if(isNaN(num)) { // don't set the value if it's not a number or coerced to a number return internalNumber } if(num % 2 !== 0) { // don't allow odd numbers return internalNumber } internalNumber = val return internalNumber } } } class MyClass { @onlyEvenNumbers accessor myEvenNumber }
因此,我們為 set() 方法新增邏輯,現在任何嘗試在我們的類別上設定 myEvenNumber 屬性的人都將通過該驗證邏輯。不錯。
現在我們有了一個很好的僅偶數裝飾器,讓我們讓它處理偶數和奇數,並提供一個選項來配置我們想要的數字類型!
幸運的是,因為這是我們在這裡編寫的看起來相當正常的 JavaScript,所以配置它以這種方式工作並不太難。我們用一個接受選項的函數包裝原始裝飾器,然後返回裝飾器。 Babel REPL
function evensOrOdds(onlyEvens = true) { return function decorator(value, context) { let internalNumber = 0 return { get() { return internalNumber }, set(val) { const num = Number(val) if(isNaN(num)) { // don't set the value if it's not a number return internalNumber } if(num % 2 !== (onlyEvens ? 0 : 1)) { return internalNumber } internalNumber = val return internalNumber } } } } class MyClass { @evensOrOdds(true) accessor myEvenNumber @evensOrOdds(false) accessor myOddNumber }
我們現在已經將裝飾器配置為接受任意選項,這允許裝飾器的使用者自訂其行為。耶。
裝飾器可以使用的另一個工具是 context.metadata。該物件被傳遞給每個裝飾器,您可以將其用於各種用途,但您需要小心,因為元資料物件對於每個裝飾器的所有呼叫都是相同的。
繼續閱讀本系列的下一篇文章,了解如何將裝飾器組合(或應用多個)到單一屬性!
以上是JavaScript 裝飾器和自動存取器的詳細內容。更多資訊請關注PHP中文網其他相關文章!