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
原文地址:https://www.cnblogs.com/mengff/p/9661648.html
时间: 2024-10-09 14:23:33