es7的decorator修飾器
裝飾器(Decorator)是一種與類(class)相關的語法,用來注釋或修改類和類方法。
decorator就是給類添加或修改類的變量與方法的。
裝飾器是一種函數,寫成@ + 函數名
。它可以放在類和類方法的定義前面。
例
@frozen class Foo {
@configurable(false)
@enumerable(true)
method() {}
@throttle(500)
expensiveMethod() {}
}
上面代碼一共使用了四個裝飾器,一個用在類本身,另外三個用在類方法。它們不僅增加了代碼的可讀性,清晰地表達了意圖,而且提供一種方便的手段,增加或修改類的功能。
1.修改類
@addType class human{} function addType(target){ target.age=27; target.name=hyh; target.sex=male; target.hight=178; console.log('此對象被修改了') } console.log(new human())
上面代碼中,@addType
就是一個裝飾器。它修改了human
這個類的行為,為它加上了靜態屬性age name sex hight等等。addType
函數的參數target
是human類本身。
2.修改類的方法
class Dabao { @setAttr cxh(){ return true } } function setAttr(targt, name, decorator) { decorator.writable = false return } var dabao = new Dabao; console.log(dabao.cxh) dabao.cxh = () => { return false } console.log(dabao.cxh)
3. 裝飾器可接受多個傳參,第一個參數為修飾target ,如果覺得一個參數不夠用,可以在裝飾器外面再封裝一層函數。
裝飾器testable
可以接受參數,這就等於可以修改裝飾器的行為。
function testable(isTestable) { return function(target) { target.isTestable = isTestable; } } @testable(true) class MyTestableClass {} MyTestableClass.isTestable // true @testable(false) class MyClass {} MyClass.isTestable // false
上面代碼中,裝飾器函數testable
是在目標類的prototype
對象上添加屬性,因此就可以在實例上調用。
下面是另外一個例子。
// mixins.js export function mixins(...list) { return function (target) { Object.assign(target.prototype, ...list) } } // main.js import { mixins } from './mixins' const Foo = { foo() { console.log('foo') } }; @mixins(Foo) class MyClass {} let obj = new MyClass(); obj.foo() // 'foo'
實際開發中,React 與 Redux 庫結合使用時,常常需要寫成下面這樣。
class MyReactComponent extends React.Component {} export default connect(mapStateToProps, mapDispatchToProps)(MyReactComponent);
有了裝飾器,就可以改寫上面的代碼。
@connect(mapStateToProps, mapDispatchToProps) export default class MyReactComponent extends React.Component {}
相對來說,后一種寫法看上去更容易理解。
4.裝飾器不能用於裝飾函數
5.Mixin
在裝飾器的基礎上,可以實現Mixin
模式。所謂Mixin
模式,就是對象繼承的一種替代方案,中文譯為“混入”(mix in),意為在一個對象之中混入另外一個對象的方法。
請看下面的例子。
const Foo = { foo() { console.log('foo') } }; class MyClass {} Object.assign(MyClass.prototype, Foo); let obj = new MyClass(); obj.foo() // 'foo'
上面代碼之中,對象Foo
有一個foo
方法,通過Object.assign
方法,可以將foo
方法“混入”MyClass
類,導致MyClass
的實例obj
對象都具有foo
方法。這就是“混入”模式的一個簡單實現。
下面,我們部署一個通用腳本mixins.js
,將 Mixin 寫成一個裝飾器。
export function mixins(...list) { return function (target) { Object.assign(target.prototype, ...list); }; }
然后,就可以使用上面這個裝飾器,為類“混入”各種方法。
import { mixins } from './mixins'; const Foo = { foo() { console.log('foo') } }; @mixins(Foo) class MyClass {} let obj = new MyClass(); obj.foo() // "foo"