ES 6装飾器のDecoratorの基本的な使い方
2885 ワード
1.基本形式
2.飾り器の実行順序
同じところにある複数の飾り器は玉葱の模型に従って外から中に入り、内から外へ実行します.
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;
}