ES6裝飾器Decorator基本用法
阿新 • • 發佈:2018-09-17
alua map white eval 更多 ast https specified 執行順序
1. 基本形式
@decorator class A {} // 等同於 class A {} A = decorator(A);
裝飾器在javascript中僅僅可以修飾類和屬性,不能修飾函數。
裝飾器對類的行為的改變,是代表編譯時發生的,而不是在運行時。
裝飾器能在編譯階段運行代碼。
裝飾器是經典的AOP模式的一種實現方式。
2. 裝飾器的執行順序
同一處的多個裝飾器是按照洋蔥模型,由外到內進入,再由內到外執行
function dec(id){ console.log(‘evaluated‘, id); return (target, property, descriptor) => console.log(‘executed‘, id); } class Example { @dec(1) @dec(2) method(){} } // evaluated 1 // evaluated 2 // executed 2 // executed 1
3. 常見的裝飾器的例子
1. 類可測試,添加一個屬性
@testable class MyTestableClass { // ... } function testable(target) { target.isTestable = true; } MyTestableClass.isTestable // true
若要進行更多的配置,可以使用高階函數,增加參數,相當於一個工廠方法,用於生產特定類型的裝飾器,例如:
//testable是一個Factory function testable(isTestable) { return function(target) { target.isTestable = isTestable; } } @testable(true) class MyTestableClass {} MyTestableClass.isTestable // true @testable(false) class MyClass {} MyClass.isTestable // false
2. 屬性readonly裝飾器
class Person { @readonly name() {return `${this.first} ${this.last}` } } function readonly(target, name, descriptor){ // descriptor對象原來的值如下 // { // value: specifiedFunction, // enumerable: false, // configurable: true, // writable: true // }; descriptor.writable = false; return descriptor; }
3. 日誌裝飾器
class Math { @log add(a, b) { return a + b; } } 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; } const math = new Math(); // passed parameters should get logged now math.add(2, 4);
3. 實現memoize,備用錄模式
class Person { @memoize get name() { return `${this.first} ${this.last}` } set name(val) { let [first, last] = val.split(‘ ‘); this.first = first; this.last = last; } } let memoized = new WeakMap(); function memoize(target, name, descriptor) { let getter = descriptor.get, setter = descriptor.set; descriptor.get = function() { let table = memoizationFor(this); if (name in table) { return table[name]; } return table[name] = getter.call(this); } descriptor.set = function(val) { let table = memoizationFor(this); setter.call(this, val); table[name] = val; } } function memoizationFor(obj) { let table = memoized.get(obj); if (!table) { table = Object.create(null); memoized.set(obj, table); } return table; }
參考:https://www.cnblogs.com/goloving/p/8001530.html
https://www.cnblogs.com/whitewolf/p/details-of-ES7-JavaScript-Decorators.html
ES6裝飾器Decorator基本用法