ES2017中的修飾器Decorator

2021-09-07 13:39:49 字數 4804 閱讀 5165

修飾器(decorator)是乙個函式,用來修改類的行為。本文將詳細介紹es2017中的修飾器decorator

es2017 引入了這項功能,目前 babel 轉碼器已經支援decorator

首先,安裝babel-corebabel-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

@testable

class mytestableclass

function

testable(target)

mytestableclass.istestable

//true

基本上,修飾器的行為就是下面這樣

@decorator

class a {}

//等同於

class a {}

a = decorator(a) || a;

修飾器對類的行為的改變,是**編譯時發生的,而不是在執行時。這意味著,修飾器能在編譯階段執行**,也就是說,修飾器本質就是編譯時執行的函式

【引數】

修飾器函式的第乙個引數,是所要修飾的目標類

function

testable(target)

如果覺得乙個引數不夠用,可以在修飾器外面再封裝一層函式

function

testable(istestable)

}@testable(

true

)class mytestableclass {}

mytestableclass.istestable

//true

@testable(

false

)class myclass {}

myclass.istestable

//false

上面**中,修飾器testable可以接受引數,這就等於可以修改修飾器的行為。

前面的例子是為類新增乙個靜態屬性,如果想新增例項屬性,可以通過目標類的prototype物件操作

function

testable(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方法

【引數】

此時,修飾器函式一共可以接受三個引數,第乙個引數是所要修飾的目標物件,第二個引數是所要修飾的屬性名,第三個引數是該屬性的描述物件

function

readonly(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,從而達到輸出日誌的目的。

修飾器有注釋的作用

@testable

class person $` }

}

從上面**中,我們一眼就能看出,person類是可測試的,而name方法是唯讀和不可列舉的

【執行順序】

如果同乙個方法有多個修飾器,會像剝洋蔥一樣,先從外到內進入,然後由內向外執行

function

dec(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。因為函式提公升,使得實際執行的**是下面這樣

@add

function

foo()

varcounter;

varadd;

counter = 0;

add = function

() ;

下面是另乙個例子

var readonly = require("some-decorator");

@readonly

function

foo()

上面**也有問題,因為實際執行是下面這樣

var

readonly;

@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之中,所以改...