decorator作爲一個提案,經過了多次修改,還未正式發佈,不過在實際編程過程中,裝飾器已經有了很多的應用。裝飾器很受歡迎的主要原因是其借鑑了java中註解的概念,讓代碼結構性和可讀性大大增強。
裝飾器的意義:更好地解釋類的相關屬性和概念,將不同的功能歸類區分,便於維護和擴展。
demo:
@Component({
tag: 'my-component',
styleUrl: 'my-component.scss'
})
export class MyComponent {
@Prop() first: string;
@Prop() last: string;
@State() isVisible: boolean = true;
render() {
return (
<p>Hello, my name is {this.first} {this.last}</p>
);
}
}
上面的代碼很好的看出當前類的一些介紹。
裝飾器的分類:
1,類的裝飾 (接受參數target)
語法:
function testable(target) {
//doSomething
}
@testable
class MyTestableClass {}
2,方法的裝飾
function readonly(target, name, descriptor){ //這裏的target不同於類的裝飾,指的是要裝飾類的prototype
// descriptor對象原來的值如下
// {
// value: specifiedFunction,
// enumerable: false,
// configurable: true,
// writable: true
// };
descriptor.writable = false;
return descriptor;
}
說明:方法裝飾器的target不同於類的裝飾,指的是要裝飾類的
實例:
class Person {
@nonenumerable
get kidCount() { return this.children.length; }
}
function nonenumerable(target, name, descriptor) {
console.log(target)
descriptor.enumerable = false;
return descriptor;
}
裝飾器的高級用法:
從裝飾器的使用上可以看出,在使用裝飾器時,並沒有直接執行裝飾器,只是指定裝飾器,因此裝飾器可以寫成高階函數的形式,在函數裏返回一個裝飾器。在指定裝飾器時直接執行外層函數,返回一個待執行的裝飾器。
實例:
//類的裝飾器
function testable(isTestable) {
return function(target) {
target.isTestable = isTestable;
}
}
@testable(true)
class MyTestableClass {}
MyTestableClass.isTestable // true
@testable(false)
class MyClass {}
MyClass.isTestable // false
//方法裝飾器
function dec(id){
console.log('evaluated', id);
return (target, property, descriptor) => console.log('executed', id);
}
class Example {
@dec(1)
@dec(2)
method(){}
}
一個很重要的注意事項:
裝飾器不能用於函數,因爲函數存在提升。(存在函數提升的原因是js解釋器在對js代碼進行詞法分析時,會先去進行函數的定義,對於函數表達式不會存在變量提升也是基於該原因,具體可以去研究js執行上下文隊列的相關知識)
實例:
var counter = 0;
var add = function () {
counter++;
};
@add
function foo() {
}
實際上運行時:(上下文入棧順序)
@add
function foo() {
}
var counter;
var add;
counter = 0;
add = function () {
counter++;
};
mixin
自定義的混入對象方法的函數,可以根據實際業務場景進行封裝。
比如:
export function mixins(...list) {
return function (target) {
Object.assign(target.prototype, ...list);
};
}
幾個重要的庫:
1,core-decorators.js
core-decorators.js是一個第三方模塊,提供了幾個常見的裝飾器,通過它可以更好地理解裝飾器。
比如:@readonly
import { readonly } from 'core-decorators';
class Meal {
@readonly
entree = 'steak';
}
var dinner = new Meal();
dinner.entree = 'salmon';
2,Trait
traits-decorator這個第三方模塊這個模塊提供的traits
裝飾器,不僅可以接受對象,還可以接受 ES6 類作爲參數。
實例:
import { traits } from 'traits-decorator';
class TFoo {
foo() { console.log('foo') }
}
const TBar = {
bar() { console.log('bar') }
};
@traits(TFoo, TBar)
class MyClass { }
let obj = new MyClass();
obj.foo() // foo
obj.bar() // bar