類的修飾
許多物件導向的語言都有修飾起函式,用來修改類的行為
@testable
class MyTestableClass{
}
function testable(target){
target.isTestable = true
}
MyTestableClass.isTestable // true
複製程式碼
上面程式碼中,@testable就是修飾器。它修改了MyTestableClass這個類的行為,為它加上了靜態屬性isTestable。testable函式的引數target是MyTestableClass類本身。也就是說,修飾器是一個對類進行處理的函式。修飾器函式的第一個引數,就是所要修飾的目標類
如果覺得一個引數不夠用,可以在修飾器外面再封裝一層函式
function testable(isTestable){
return function(target){
target.isTestable = isTestable
}
}
@testable(true)
class MyTestableClass{}
MyTestableClass.isTestable // true
@testable(false)
class MyTestableClass{}
MyTestableClass.isTestable // false
複製程式碼
修飾器對類的行為的改變,是程式碼編譯時發生的,而不是在執行時。
如果想新增例項屬性,可以通過目標類的prototype物件操作
function testable(target){
target.prototype.isTestable = true
}
@testable
class MyTestableClass{}
let obj = new MyTestableClass();
obj.isTestable // true
複製程式碼
方法的修飾
修飾器不僅可以修飾類,還可以修飾類的屬性
class Person{
@readonly
name() {return `${this.first} ${this.last}`}
}
複製程式碼
修飾器readonly用來修飾 類 的name方法,修飾器readonly一共可以接受三個引數。
function readonly(target, name, descriptor){
// descriptor物件原來的值如下
// {
// value: specifiedFunction,
// enumerable: false,
// configurable: true,
// writable: true
// };
descriptor.writable = false;
return descriptor;
}
readonly(Person.prototype, 'name', descriptor)
複製程式碼
修飾器第一個引數是類的原型物件,上例是Person.prototype,修飾器的本意是要 修飾類的例項,但是這個例項還沒有生成,所以智慧去修飾原型,第二個引數是所要修飾的屬性名,第三個引數是該屬性的描述物件。
多個修飾器的執行
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
複製程式碼
如果同一個方法有多個修飾器,會像剝洋蔥一樣,先從外到內進入,然後由內向外執行。
外層修飾器@dec(1)
先進入,但是內層修飾器@dec(2)
先執行。