修飾器(decorator)是乙個函式,用來修改類的行為。
es6 引入了這項功能,目前 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
@testable classmytestableclass
function testable(target)
mytestableclass.istestable
//true
基本上,修飾器的行為就是下面這樣
@decoratorclass
a {}
//等同於
class
a {}
a = decorator(a) || a;
修飾器對類的行為的改變,是**編譯時發生的,而不是在執行時。這意味著,修飾器能在編譯階段執行**,也就是說,修飾器本質就是編譯時執行的函式
1、引數
修飾器函式的第乙個引數,是所要修飾的目標類
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
修飾器不僅可以修飾類,還可以修飾類的屬性
classperson $` }
}
上面**中,修飾器readonly
用來修飾「類」的name
方法
1、引數
此時,修飾器函式一共可以接受三個引數,第乙個引數是所要修飾的目標物件,第二個引數是所要修飾的屬性名,第三個引數是該屬性的描述物件
function readonly(target, name, descriptor);
descriptor.writable = false;
return
descriptor;
}readonly(person.prototype, '
name
', descriptor);
//類似於
object.defineproperty(person.prototype, '
name
', descriptor);
上面**說明,修飾器(readonly)會修改屬性的描述物件(descriptor),然後被修改的描述物件再用來定義屬性。
下面是另乙個例子,修改屬性描述物件的enumerable
屬性,使得該屬性不可遍歷
classperson
}function nonenumerable(target, name, descriptor)
2、日誌應用
下面的@log
修飾器,可以起到輸出日誌的作用
classmath
}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
方法是唯讀和不可列舉的
3、執行順序
如果同乙個方法有多個修飾器,會像剝洋蔥一樣,先從外到內進入,然後由內向外執行
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。因為函式提公升,使得實際執行的**是下面這樣
@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)return
function()
}
ES6裡的修飾器Decorator
修飾器 decorator 是乙個函式,用來修改類的行為。es6 引入了這項功能,目前 babel 轉碼器已經支援decorator 首先,安裝babel core和babel plugin transform decorators。由於後者包括在babel preset stage 0之中,所以改...
es6 使用修飾器實現Mixin模式
在修飾器的基礎上,可以實現mixin模式。所謂mixin模式,就是物件繼承的一種替代方案,中文譯為 混入 mix in 意為在乙個物件之中混入另外乙個物件的方法。請看下面的例子。const foo class myclass object assign myclass prototype foo l...
ES6的 迭代器
1,iterator 迭代器是es6提出的一種新的遍歷機制,目的是讓各種資料結構可方便地被訪問。可迭代物件由symbol.iterator實現,用symbol.iterator作為物件的屬性,鍵symbol.iterator的值是個函式,函式的執行返回乙個陣列的迭代器,可見 迭代器物件與symbol...