官术网_书友最值得收藏!

Decorators

Decorators were proposed in ECMAScript 2016 (https://github.com/wycats/javascript-decorators). They are similar to Java annotations--they also add metadata to class declaration, method, property, and the function's parameter, but they are more powerful. They add new behaviors to their targets. With decorators, we can run arbitrary code before, after, or around the target execution, like in aspect-oriented programming, or even replace the target with a new definition. In TypeScript, you can decorate constructors, methods, properties, and parameters. Every decorator begins with the @ character followed by the name of the decorator.

How does it work under the hood that takes its target as argument? Let's implement a classic example with a logging functionality. We would like to implement a method decorator @log. A method decorator accepts three arguments: an instance of the class on which the method is defined, a key for the property, and the property descriptor (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty).

If the method decorator returns a value, it will be used as a new property descriptor for this method:

const log = (target: Object, key: string | symbol, descriptor: PropertyDescriptor) => {
// save a reference to the original method
var originalMethod = descriptor.value;
// replace the original function
descriptor.value = function(...args: any[]) {
console.log("Arguments: ", args.join(", "));
const result = originalMethod.apply(target, args);
console.log("Result: ", result);
return result;
}
return descriptor;
}

class Rectangle {
@log
area(height: number, width: number) {
return height * width;
}
}

let rect = new Rectangle();
let area = rect.area(2, 3);

This decorator logs received arguments and return values. Decorators can be composed and customized with parameters too. You can write the following, for instance:

class Rectangle {
@log("debug")
@persist("localStorage")
area(height: number, width: number) {
return height * width;
}
}

Angular offers different types of decorators that are used for dependency injection or adding metadata information at compilation time:

  • Class decorators such as @NgModule, @Component, and @Injectable
  • Property decorators such as @Input and @Output
  • Method decorators such as @HostListener
  • Parameter decorators such as @Inject

TypeScript compiler is able to emit some design-time type metadata for decorators. To access this information, we have to install a Polyfill called reflect-metadata:

npm install reflect-metadata --save

Now we can access, for example, the type of the property (key) on the target object as follows:

let typeOfKey = Reflect.getMetadata("design:type", target, key);
Refer to the official TypeScript documentation to learn more about decorators and reflect metadata API ( http://www.typescriptlang.org/docs/handbook/decorators.html).
In TypeScript, Angular applications, decorators are enabled by setting the compiler options emitDecoratorMetadata and experimentalDecorators to true (compiler options are described later on).
主站蜘蛛池模板: 新宁县| 锦屏县| 甘谷县| 泰兴市| 额敏县| 资源县| 太湖县| 怀柔区| 新兴县| 金寨县| 林口县| 奉新县| 荔浦县| 亚东县| 翼城县| 武川县| 海城市| 东乡县| 招远市| 嘉善县| 竹山县| 万山特区| 衡阳县| 贵州省| 古浪县| 黑水县| 临沧市| 公安县| 滨州市| 黄山市| 龙川县| 广饶县| 同江市| 革吉县| 渑池县| 淄博市| 麦盖提县| 临洮县| 栖霞市| 昌宁县| 阿城市|