修飾器(decorator)是乙個函式,用來修改類的行為。本文將詳細介紹es2017中的修飾器decorator
es2017 引入了這項功能,目前 babel 轉碼器已經支援decorator
首先,安裝babel-core
和babel-plugin-transform-decorators
。由於後者包括在babel-preset-stage-0
之中,所以改為安裝babel-preset-stage-0
亦可
$ npm install babel-core babel-plugin-transform-decorators
然後,設定配置檔案.babelrc
這時,babel就可以對decorator轉碼了
指令碼中開啟的命令如下
babel.transform("code", )
下面**中,@testable
就是乙個修飾器。它修改了mytestableclass
這個類的行為,為它加上了靜態屬性istestable
@testableclass mytestableclass
function
testable(target)
mytestableclass.istestable
//true
基本上,修飾器的行為就是下面這樣
@decoratorclass a {}
//等同於
class a {}
a = decorator(a) || a;
修飾器對類的行為的改變,是**編譯時發生的,而不是在執行時。這意味著,修飾器能在編譯階段執行**,也就是說,修飾器本質就是編譯時執行的函式
【引數】
修飾器函式的第乙個引數,是所要修飾的目標類
functiontestable(target)
如果覺得乙個引數不夠用,可以在修飾器外面再封裝一層函式
functiontestable(istestable)
}@testable(
true
)class mytestableclass {}
mytestableclass.istestable
//true
@testable(
false
)class myclass {}
myclass.istestable
//false
上面**中,修飾器testable
可以接受引數,這就等於可以修改修飾器的行為。
前面的例子是為類新增乙個靜態屬性,如果想新增例項屬性,可以通過目標類的prototype
物件操作
functiontestable(target)
@testable
class mytestableclass {}
let obj = new
mytestableclass();
obj.istestable
//true
【mixins】
下面是另外乙個例子
//mixins.js
export function
mixins(...list) }//
main.js
import from './mixins'const foo =
};@mixins(foo)
class myclass {}
let obj = new
myclass();
obj.foo()
//'foo'
上面**通過修飾器mixins
,把foo
類的方法新增到了myclass
的例項上面。可以用object.assign()
模擬這個功能
const foo =};class myclass {}
object.assign(myclass.prototype, foo);
let obj = new
myclass();
obj.foo()
//'foo'
修飾器不僅可以修飾類,還可以修飾類的屬性
class person $` }}
上面**中,修飾器readonly
用來修飾「類」的name
方法
【引數】
此時,修飾器函式一共可以接受三個引數,第乙個引數是所要修飾的目標物件,第二個引數是所要修飾的屬性名,第三個引數是該屬性的描述物件
functionreadonly(target, name, descriptor);
descriptor.writable = false;
return
descriptor;
}readonly(person.prototype, 'name', descriptor);
//類似於
object.defineproperty(person.prototype, 'name', descriptor);
上面**說明,修飾器(readonly)會修改屬性的描述物件(descriptor),然後被修改的描述物件再用來定義屬性。
下面是另乙個例子,修改屬性描述物件的enumerable
屬性,使得該屬性不可遍歷
class person}function
nonenumerable(target, name, descriptor)
【日誌應用】
下面的@log
修飾器,可以起到輸出日誌的作用
class math}function
log(target, name, descriptor) " with
`, arguments);
, arguments);
};return
descriptor;
}const math = new
math();
//passed parameters should get logged now
math.add(2, 4);
上面**中,@log
修飾器的作用就是在執行原始的操作之前,執行一次console.log
,從而達到輸出日誌的目的。
修飾器有注釋的作用
@testableclass person $` }
}
從上面**中,我們一眼就能看出,person
類是可測試的,而name
方法是唯讀和不可列舉的
【執行順序】
如果同乙個方法有多個修飾器,會像剝洋蔥一樣,先從外到內進入,然後由內向外執行
functiondec(id)
class example }//
evaluated 1
//evaluated 2
//executed 2
//executed 1
上面**中,外層修飾器@dec(1)
先進入,但是內層修飾器@dec(2)
先執行
除了注釋,修飾器還能用來型別檢查。所以,對於類來說,這項功能相當有用。從長期來看,它將是js**靜態分析的重要工具
修飾器只能用於類和類的方法,不能用於函式,因為存在函式提公升
var counter = 0;var add = function
() ;
@add
function
foo()
上面的**,意圖是執行後counter
等於1,但是實際上結果是counter
等於0。因為函式提公升,使得實際執行的**是下面這樣
@addfunction
foo()
varcounter;
varadd;
counter = 0;
add = function
() ;
下面是另乙個例子
var readonly = require("some-decorator");@readonly
function
foo()
上面**也有問題,因為實際執行是下面這樣
varreadonly;
@readonly
function
foo()
readonly = require("some-decorator");
總之,由於存在函式提公升,使得修飾器不能用於函式。類是不會提公升的,所以就沒有這方面的問題。
另一方面,如果一定要修飾函式,可以採用高階函式的形式直接執行
function
dosomething(name)
function
return
function
() }
es6 Decorator類的修飾器
許多物件導向的語言都有修飾器 decorator 函式,用來修改類的行為。目前,有乙個提案將這項功能,引入了 ecmascript。testable class mytestableclass function testable target mytestableclass istestable t...
ES6裡的修飾器Decorator
修飾器 decorator 是乙個函式,用來修改類的行為。es6 引入了這項功能,目前 babel 轉碼器已經支援decorator 首先,安裝babel core和babel plugin transform decorators。由於後者包括在babel preset stage 0之中,所以改...
ES6裡的修飾器Decorator
修飾器 decorator 是乙個函式,用來修改類的行為。es6 引入了這項功能,目前 babel 轉碼器已經支援decorator 首先,安裝babel core和babel plugin transform decorators。由於後者包括在babel preset stage 0之中,所以改...