您好,登錄后才能下訂單哦!
這篇文章主要介紹“es6中裝飾器怎么實現”,在日常操作中,相信很多人在es6中裝飾器怎么實現問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”es6中裝飾器怎么實現”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
在es6中,裝飾器(Decorator)是一種與類(class)相關的語法,用來注釋或修改類和類方法;裝飾器其實就是一個編譯時執行的函數,語法“@函數名”,通常放在類和類方法的定義前面。裝飾器有兩種:類裝飾器和類方法裝飾器。
本教程操作環境:windows7系統、ECMAScript 6版、Dell G3電腦。
裝飾器模式(Decorator Pattern)允許向一個現有的對象添加新的功能,同時又不改變其結構。這種類型的設計模式屬于結構型模式,它是作為現有的類的一個包裝。
這種模式創建了一個裝飾類,用來包裝原有的類,并在保持類方法簽名完整性的前提下,提供了額外的功能。
在 ES6 中,裝飾器(Decorator)是一種與類相關的語法,用來注釋或修改類和類方法。
裝飾器其實就是一個函數,通常放在類和類方法的前面。
裝飾器對類的行為的改變,是代碼編譯時發生的,而不是在運行時;裝飾器的本質就是編譯時執行的函數
裝飾器可以用來裝飾整個類
@decorateClass class Example { @decorateMethods method(){} }
在上面的代碼中使用了兩個裝飾器,其中 @decorateClass()
裝飾器用在類本身,用于增加或修改類的功能;@decorateMethods()
裝飾器用在類的方法,用于注釋或修改類方法。
裝飾器只能用于類和類的方法,不能用于函數,因為存在函數提升。
裝飾器只能用于類和類的方法,下面我們分別看下兩種類型的裝飾器的使用
1、類裝飾器
類裝飾器用來裝飾整個類
類裝飾器的參數
target: 類本身,也相當于是 類的構造函數:Class.prototype.constructor。
@decorateClass class Example { //... } function decorateClass(target) { target.isTestClass = true }
如上面代碼中,裝飾器 @decorateClass 修改了 Example 整個類的行為,為 Example 類添加了靜態屬性 isTestClass。裝飾器就是一個函數,decorateClass 函數中的參數 target 就是 Example 類本身,也相當于是類的構造函數 Example.prototype.constructor.
裝飾器傳參
上面實現的裝飾器在使用時是不能傳入參數的,如果想要在使用裝飾器是傳入參數,可以在裝飾器外面再封裝一層函數
@decorateClass(true) class Example { //... } function decorateClass(isTestClass) { return function(target) { target.isTestClass = isTestClass } }
上面代碼中實現的裝飾器在使用時可以傳遞參數,這樣就可以根據不同的場景來修改裝飾器的行為。
實際開發中,React 與 Redux 庫結合使用時,常常需要寫成下面這樣。
class MyReactComponent extends React.Component {} export default connect(mapStateToProps, mapDispatchToProps)(MyReactComponent);
有了裝飾器,就可以改寫上面的代碼。
@connect(mapStateToProps, mapDispatchToProps) export default class MyReactComponent extends React.Component {}
2、類方法裝飾器
類方法裝飾器用來裝飾類的方法
類方法裝飾器的參數
target:
裝飾器修飾的類方法是靜態方法:target 為類的構造函數
裝飾器修飾的類方法是實例方法:target 為類的原型對象
method:被修飾的類方法的名稱
descriptor:被修飾成員的屬性描述符
// descriptor對象原來的值如下 { value: specifiedFunction, enumerable: false, configurable: true, writable: true };
class Example { @log instanceMethod() { } @log static staticMethod() { } } function log(target, methodName, descriptor) { const oldValue = descriptor.value; descriptor.value = function() { console.log(`Calling ${name} with`, arguments); return oldValue.apply(this, arguments); }; return descriptor; }
如上面代碼中,裝飾器 @log 分別裝飾了實例方法 instanceMethod 和 靜態方法 staticMethod。@log 裝飾器的作用是在執行原始的操作之前,執行 console.log 來輸出日志。
類方法裝飾器傳參
上面實現的裝飾器在使用時是不能傳入參數的,如果想要在使用裝飾器是傳入參數,可以在裝飾器外面再封裝一層函數
class Example { @log(1) instanceMethod() { } @log(2) static staticMethod() { } } function log(id) { return (target, methodName, descriptor) => { const oldValue = descriptor.value; descriptor.value = function() { console.log(`Calling ${name} with`, arguments, `this id is ${id}`); return oldValue.apply(this, arguments); }; return descriptor; } }
上面代碼中實現的裝飾器在使用時可以傳遞參數,這樣就可以根據不同的場景來修改裝飾器的行為。
如果在一個類中,同時使用裝飾器修飾類和類的方法,那么裝飾器的執行順序是:先執行類方法的裝飾器,再執行類裝飾器。
如果同一個類或同一個類方法有多個裝飾器,會像剝洋蔥一樣,先從外到內進入,然后由內到外執行。
// 類裝飾器 function decoratorClass(id){ console.log('decoratorClass evaluated', id); return (target) => { // target 類的構造函數 console.log('target 類的構造函數:',target) console.log('decoratorClass executed', id); } } // 方法裝飾器 function decoratorMethods(id){ console.log('decoratorMethods evaluated', id); return (target, property, descriptor) => { // target 代表 // process.nextTick((() => { target.abc = 123 console.log('method target',target) // })) console.log('decoratorMethods executed', id); } } @decoratorClass(1) @decoratorClass(2) class Example { @decoratorMethods(1) @decoratorMethods(2) method(){} } /** 輸入日志 **/ // decoratorMethods evaluated 1 // decoratorMethods evaluated 2 // method target Example { abc: 123 } // decoratorMethods executed 2 // method target Example { abc: 123 } // decoratorMethods executed 1 // decoratorClass evaluated 1 // decoratorClass evaluated 2 // target 類的構造函數: [Function: Example] // decoratorClass executed 2 // target 類的構造函數: [Function: Example] // decoratorClass executed 1
如上面代碼中,會先執行類方法的裝飾器 @decoratorMethods(1) 和 @decoratorMethods(2),執行完后再執行類裝飾器 @decoratorClass(1) 和 @decoratorClass(2)
上面代碼中的類方法裝飾器中,外層裝飾器 @decoratorMethods(1) 先進入,但是內層裝飾器 @decoratorMethods(2) 先執行。類裝飾器同理。
function log(target, name, descriptor) { var oldValue = descriptor.value; descriptor.value = function () { console.log(`Calling "${name}" with`, arguments); return oldValue.apply(null, arguments); } return descriptor; } // 日志應用 class Maths { @log add(a, b) { return a + b; } } const math = new Maths(); // passed parameters should get logged now math.add(2, 4);
到此,關于“es6中裝飾器怎么實現”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。