diff --git a/docs/class.md b/docs/class.md index f435b14..2594c36 100644 --- a/docs/class.md +++ b/docs/class.md @@ -823,542 +823,3 @@ var y = new Rectangle(3, 4); // 正确 注意,在函数外部,使用`new.target`会报错。 -## 修饰器 - -### 类的修饰 - -修饰器(Decorator)是一个表达式,用来修改类的行为。这是ES7的一个[提案](https://github.com/wycats/javascript-decorators),目前Babel转码器已经支持。 - -修饰器对类的行为的改变,是代码编译时发生的,而不是在运行时。这意味着,修饰器能在编译阶段运行代码。 - -```javascript -function testable(target) { - target.isTestable = true; -} - -@testable -class MyTestableClass () {} - -console.log(MyTestableClass.isTestable) // true -``` - -上面代码中,`@testable`就是一个修饰器。它修改了MyTestableClass这个类的行为,为它加上了静态属性isTestable。 - -基本上,修饰器的行为就是下面这样。 - -```javascript -@decorator -class A {} - -// 等同于 - -class A {} -A = decorator(A) || A; -``` - -也就是说,修饰器本质上就是能在编译时执行的函数。 - -修饰器函数可以接受三个参数,依次是目标函数、属性名和该属性的描述对象。后两个参数可省略。上面代码中,testable函数的参数target,就是所要修饰的对象。如果希望修饰器的行为,能够根据目标对象的不同而不同,就要在外面再封装一层函数。 - -```javascript -function testable(isTestable) { - return function(target) { - target.isTestable = isTestable; - } -} - -@testable(true) class MyTestableClass () {} -console.log(MyTestableClass.isTestable) // true - -@testable(false) class MyClass () {} -console.log(MyClass.isTestable) // false -``` - -上面代码中,修饰器testable可以接受参数,这就等于可以修改修饰器的行为。 - -如果想要为类的实例添加方法,可以在修饰器函数中,为目标类的prototype属性添加方法。 - -```javascript -function testable(target) { - target.prototype.isTestable = true; -} - -@testable -class MyTestableClass () {} - -let obj = new MyClass(); - -console.log(obj.isTestable) // true -``` - -上面代码中,修饰器函数testable是在目标类的prototype属性添加属性,因此就可以在类的实例上调用添加的属性。 - -下面是另外一个例子。 - -```javascript -// 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' -``` - -上面代码通过修饰器mixins,可以为类添加指定的方法。 - -修饰器可以用`Object.assign()`模拟。 - -```javascript -const Foo = { - foo() { console.log('foo') } -} - -class MyClass {} - -Object.assign(MyClass.prototype, Foo); - -let obj = new MyClass(); -obj.foo() // 'foo' -``` - -### 方法的修饰 - -修饰器不仅可以修饰类,还可以修饰类的属性。 - -```javascript -class Person { - @readonly - name() { return `${this.first} ${this.last}` } -} -``` - -上面代码中,修饰器readonly用来修饰”类“的name方法。 - -此时,修饰器函数一共可以接受三个参数,第一个参数是所要修饰的目标对象,第二个参数是所要修饰的属性名,第三个参数是该属性的描述对象。 - -```javascript -readonly(Person.prototype, 'name', descriptor); - -function readonly(target, name, descriptor){ - // descriptor对象原来的值如下 - // { - // value: specifiedFunction, - // enumerable: false, - // configurable: true, - // writable: true - // }; - descriptor.writable = false; - return descriptor; -} - -Object.defineProperty(Person.prototype, 'name', descriptor); -``` - -上面代码说明,修饰器(readonly)会修改属性的描述对象(descriptor),然后被修改的描述对象再用来定义属性。下面是另一个例子。 - -```javascript -class Person { - @nonenumerable - get kidCount() { return this.children.length; } -} - -function nonenumerable(target, name, descriptor) { - descriptor.enumerable = false; - return descriptor; -} -``` - -修饰器有注释的作用。 - -```javascript -@testable -class Person { - @readonly - @nonenumerable - name() { return `${this.first} ${this.last}` } -} -``` - -从上面代码中,我们一眼就能看出,MyTestableClass类是可测试的,而name方法是只读和不可枚举的。 - -除了注释,修饰器还能用来类型检查。所以,对于Class来说,这项功能相当有用。从长期来看,它将是JavaScript代码静态分析的重要工具。 - - -### 为什么修饰器不能用于函数? - -修饰器只能用于类和类的方法,不能用于函数,因为存在函数提升。 - -```javascript -var counter = 0; - -var add = function () { - counter++; -}; - -@add -function foo() { -} -``` - -上面的代码,意图是执行后,counter等于1,但是实际上结果是couter等于0。因为函数提升,使得实际执行的代码是下面这样。 - -```javascript -var counter; -var add; - -@add -function foo() { -} - -counter = 0; - -add = function () { - counter++; -}; -``` - -下面是另一个例子。 - -```javascript -var readOnly = require("some-decorator"); - -@readOnly -function foo() { -} -``` - -上面代码也有问题,因为实际执行是下面这样。 - -```javascript -var readOnly; - -@readOnly -function foo() { -} - -readOnly = require("some-decorator"); -``` - -总之,由于存在函数提升,使得修饰器不能用于函数。类是不会提升的,所以就没有这方面的问题。 - -### core-decorators.js - -[core-decorators.js](https://github.com/jayphelps/core-decorators.js)是一个第三方模块,提供了几个常见的修饰器,通过它可以更好地理解修饰器。 - -**(1)@autobind** - -autobind修饰器使得方法中的this对象,绑定原始对象。 - -```javascript -import { autobind } from 'core-decorators'; - -class Person { - @autobind - getPerson() { - return this; - } -} - -let person = new Person(); -let getPerson = person.getPerson; - -getPerson() === person; -// true -``` - -**(2)@readonly** - -readonly修饰器是的属性或方法不可写。 - -```javascript -import { readonly } from 'core-decorators'; - -class Meal { - @readonly - entree = 'steak'; -} - -var dinner = new Meal(); -dinner.entree = 'salmon'; -// Cannot assign to read only property 'entree' of [object Object] -``` - -**(3)@override** - -override修饰器检查子类的方法,是否正确覆盖了父类的同名方法,如果不正确会报错。 - -```javascript -import { override } from 'core-decorators'; - -class Parent { - speak(first, second) {} -} - -class Child extends Parent { - @override - speak() {} - // SyntaxError: Child#speak() does not properly override Parent#speak(first, second) -} - -// or - -class Child extends Parent { - @override - speaks() {} - // SyntaxError: No descriptor matching Child#speaks() was found on the prototype chain. - // - // Did you mean "speak"? -} -``` - -**(4)@deprecate (别名@deprecated)** - -deprecate或deprecated修饰器在控制台显示一条警告,表示该方法将废除。 - -```javascript -import { deprecate } from 'core-decorators'; - -class Person { - @deprecate - facepalm() {} - - @deprecate('We stopped facepalming') - facepalmHard() {} - - @deprecate('We stopped facepalming', { url: 'http://knowyourmeme.com/memes/facepalm' }) - facepalmHarder() {} -} - -let person = new Person(); - -person.facepalm(); -// DEPRECATION Person#facepalm: This function will be removed in future versions. - -person.facepalmHard(); -// DEPRECATION Person#facepalmHard: We stopped facepalming - -person.facepalmHarder(); -// DEPRECATION Person#facepalmHarder: We stopped facepalming -// -// See http://knowyourmeme.com/memes/facepalm for more details. -// -``` - -**(5)@suppressWarnings** - -suppressWarnings修饰器抑制decorated修饰器导致的`console.warn()`调用。但是,异步代码出发的调用除外。 - -```javascript -import { suppressWarnings } from 'core-decorators'; - -class Person { - @deprecated - facepalm() {} - - @suppressWarnings - facepalmWithoutWarning() { - this.facepalm(); - } -} - -let person = new Person(); - -person.facepalmWithoutWarning(); -// no warning is logged -``` - -### Mixin - -在修饰器的基础上,可以实现Mixin模式。所谓Mixin模式,就是对象继承的一种替代方案,中文译为“混入”(mix in),意为在一个对象之中混入另外一个对象的方法。 - -请看下面的例子。 - -```javascript -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写成一个修饰器。 - -```javascript -export function mixins(...list) { - return function (target) { - Object.assign(target.prototype, ...list); - }; -} -``` - -然后,就可以使用上面这个修饰器,为类“混入”各种方法。 - -```javascript -import { mixins } from './mixins' - -const Foo = { - foo() { console.log('foo') } -}; - -@mixins(Foo) -class MyClass {} - -let obj = new MyClass(); - -obj.foo() // "foo" -``` - -通过mixins这个修饰器,实现了在MyClass类上面“混入”Foo对象的foo方法。 - -### Trait - -Trait也是一种修饰器,功能与Mixin类型,但是提供更多功能,比如防止同名方法的冲突、排除混入某些方法、为混入的方法起别名等等。 - -下面采用[traits-decorator](https://github.com/CocktailJS/traits-decorator)这个第三方模块作为例子。这个模块提供的traits修饰器,不仅可以接受对象,还可以接受ES6类作为参数。 - -```javascript -import {traits } from 'traits-decorator' - -class TFoo { - foo() { console.log('foo') } -} - -const TBar = { - bar() { console.log('bar') } -} - -@traits(TFoo, TBar) -class MyClass { } - -let obj = new MyClass() -obj.foo() // foo -obj.bar() // bar -``` - -上面代码中,通过traits修饰器,在MyClass类上面“混入”了TFoo类的foo方法和TBar对象的bar方法。 - -Trait不允许“混入”同名方法。 - -```javascript -import {traits } from 'traits-decorator' - -class TFoo { - foo() { console.log('foo') } -} - -const TBar = { - bar() { console.log('bar') }, - foo() { console.log('foo') } -} - -@traits(TFoo, TBar) -class MyClass { } -// 报错 -// throw new Error('Method named: ' + methodName + ' is defined twice.'); -// ^ -// Error: Method named: foo is defined twice. -``` - -上面代码中,TFoo和TBar都有foo方法,结果traits修饰器报错。 - -一种解决方法是排除TBar的foo方法。 - -```javascript -import { traits, excludes } from 'traits-decorator' - -class TFoo { - foo() { console.log('foo') } -} - -const TBar = { - bar() { console.log('bar') }, - foo() { console.log('foo') } -} - -@traits(TFoo, TBar::excludes('foo')) -class MyClass { } - -let obj = new MyClass() -obj.foo() // foo -obj.bar() // bar -``` - -上面代码使用绑定运算符(::)在TBar上排除foo方法,混入时就不会报错了。 - -另一种方法是为TBar的foo方法起一个别名。 - -```javascript -import { traits, alias } from 'traits-decorator' - -class TFoo { - foo() { console.log('foo') } -} - -const TBar = { - bar() { console.log('bar') }, - foo() { console.log('foo') } -} - -@traits(TFoo, TBar::alias({foo: 'aliasFoo'})) -class MyClass { } - -let obj = new MyClass() -obj.foo() // foo -obj.aliasFoo() // foo -obj.bar() // bar -``` - -上面代码为TBar的foo方法起了别名aliasFoo,于是MyClass也可以混入TBar的foo方法了。 - -alias和excludes方法,可以结合起来使用。 - -```javascript -@traits(TExample::excludes('foo','bar')::alias({baz:'exampleBaz'})) -class MyClass {} -``` - -上面代码排除了TExample的foo方法和bar方法,为baz方法起了别名exampleBaz。 - -as方法则为上面的代码提供了另一种写法。 - -```javascript -@traits(TExample::as({excludes:['foo', 'bar'], alias: {baz: 'exampleBaz'}})) -class MyClass {} -``` - -### Babel转码器的支持 - -目前,Babel转码器已经支持Decorator,命令行的用法如下。 - -```bash -$ babel --optional es7.decorators -``` - -脚本中打开的命令如下。 - -```javascript -babel.transfrom("code", {optional: ["es7.decorators"]}) -``` - -Babel的官方网站提供一个[在线转码器](https://babeljs.io/repl/),只要勾选Experimental,就能支持Decorator的在线转码。 diff --git a/docs/decorator.md b/docs/decorator.md new file mode 100644 index 0000000..7e1abac --- /dev/null +++ b/docs/decorator.md @@ -0,0 +1,539 @@ +# 修饰器 + +## 类的修饰 + +修饰器(Decorator)是一个表达式,用来修改类的行为。这是ES7的一个[提案](https://github.com/wycats/javascript-decorators),目前Babel转码器已经支持。 + +修饰器对类的行为的改变,是代码编译时发生的,而不是在运行时。这意味着,修饰器能在编译阶段运行代码。 + +```javascript +function testable(target) { + target.isTestable = true; +} + +@testable +class MyTestableClass () {} + +console.log(MyTestableClass.isTestable) // true +``` + +上面代码中,`@testable`就是一个修饰器。它修改了MyTestableClass这个类的行为,为它加上了静态属性isTestable。 + +基本上,修饰器的行为就是下面这样。 + +```javascript +@decorator +class A {} + +// 等同于 + +class A {} +A = decorator(A) || A; +``` + +也就是说,修饰器本质上就是能在编译时执行的函数。 + +修饰器函数可以接受三个参数,依次是目标函数、属性名和该属性的描述对象。后两个参数可省略。上面代码中,testable函数的参数target,就是所要修饰的对象。如果希望修饰器的行为,能够根据目标对象的不同而不同,就要在外面再封装一层函数。 + +```javascript +function testable(isTestable) { + return function(target) { + target.isTestable = isTestable; + } +} + +@testable(true) class MyTestableClass () {} +console.log(MyTestableClass.isTestable) // true + +@testable(false) class MyClass () {} +console.log(MyClass.isTestable) // false +``` + +上面代码中,修饰器testable可以接受参数,这就等于可以修改修饰器的行为。 + +如果想要为类的实例添加方法,可以在修饰器函数中,为目标类的prototype属性添加方法。 + +```javascript +function testable(target) { + target.prototype.isTestable = true; +} + +@testable +class MyTestableClass () {} + +let obj = new MyClass(); + +console.log(obj.isTestable) // true +``` + +上面代码中,修饰器函数testable是在目标类的prototype属性添加属性,因此就可以在类的实例上调用添加的属性。 + +下面是另外一个例子。 + +```javascript +// 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' +``` + +上面代码通过修饰器mixins,可以为类添加指定的方法。 + +修饰器可以用`Object.assign()`模拟。 + +```javascript +const Foo = { + foo() { console.log('foo') } +} + +class MyClass {} + +Object.assign(MyClass.prototype, Foo); + +let obj = new MyClass(); +obj.foo() // 'foo' +``` + +## 方法的修饰 + +修饰器不仅可以修饰类,还可以修饰类的属性。 + +```javascript +class Person { + @readonly + name() { return `${this.first} ${this.last}` } +} +``` + +上面代码中,修饰器readonly用来修饰”类“的name方法。 + +此时,修饰器函数一共可以接受三个参数,第一个参数是所要修饰的目标对象,第二个参数是所要修饰的属性名,第三个参数是该属性的描述对象。 + +```javascript +readonly(Person.prototype, 'name', descriptor); + +function readonly(target, name, descriptor){ + // descriptor对象原来的值如下 + // { + // value: specifiedFunction, + // enumerable: false, + // configurable: true, + // writable: true + // }; + descriptor.writable = false; + return descriptor; +} + +Object.defineProperty(Person.prototype, 'name', descriptor); +``` + +上面代码说明,修饰器(readonly)会修改属性的描述对象(descriptor),然后被修改的描述对象再用来定义属性。下面是另一个例子。 + +```javascript +class Person { + @nonenumerable + get kidCount() { return this.children.length; } +} + +function nonenumerable(target, name, descriptor) { + descriptor.enumerable = false; + return descriptor; +} +``` + +修饰器有注释的作用。 + +```javascript +@testable +class Person { + @readonly + @nonenumerable + name() { return `${this.first} ${this.last}` } +} +``` + +从上面代码中,我们一眼就能看出,MyTestableClass类是可测试的,而name方法是只读和不可枚举的。 + +除了注释,修饰器还能用来类型检查。所以,对于Class来说,这项功能相当有用。从长期来看,它将是JavaScript代码静态分析的重要工具。 + + +## 为什么修饰器不能用于函数? + +修饰器只能用于类和类的方法,不能用于函数,因为存在函数提升。 + +```javascript +var counter = 0; + +var add = function () { + counter++; +}; + +@add +function foo() { +} +``` + +上面的代码,意图是执行后,counter等于1,但是实际上结果是couter等于0。因为函数提升,使得实际执行的代码是下面这样。 + +```javascript +var counter; +var add; + +@add +function foo() { +} + +counter = 0; + +add = function () { + counter++; +}; +``` + +下面是另一个例子。 + +```javascript +var readOnly = require("some-decorator"); + +@readOnly +function foo() { +} +``` + +上面代码也有问题,因为实际执行是下面这样。 + +```javascript +var readOnly; + +@readOnly +function foo() { +} + +readOnly = require("some-decorator"); +``` + +总之,由于存在函数提升,使得修饰器不能用于函数。类是不会提升的,所以就没有这方面的问题。 + +## core-decorators.js + +[core-decorators.js](https://github.com/jayphelps/core-decorators.js)是一个第三方模块,提供了几个常见的修饰器,通过它可以更好地理解修饰器。 + +**(1)@autobind** + +autobind修饰器使得方法中的this对象,绑定原始对象。 + +```javascript +import { autobind } from 'core-decorators'; + +class Person { + @autobind + getPerson() { + return this; + } +} + +let person = new Person(); +let getPerson = person.getPerson; + +getPerson() === person; +// true +``` + +**(2)@readonly** + +readonly修饰器是的属性或方法不可写。 + +```javascript +import { readonly } from 'core-decorators'; + +class Meal { + @readonly + entree = 'steak'; +} + +var dinner = new Meal(); +dinner.entree = 'salmon'; +// Cannot assign to read only property 'entree' of [object Object] +``` + +**(3)@override** + +override修饰器检查子类的方法,是否正确覆盖了父类的同名方法,如果不正确会报错。 + +```javascript +import { override } from 'core-decorators'; + +class Parent { + speak(first, second) {} +} + +class Child extends Parent { + @override + speak() {} + // SyntaxError: Child#speak() does not properly override Parent#speak(first, second) +} + +// or + +class Child extends Parent { + @override + speaks() {} + // SyntaxError: No descriptor matching Child#speaks() was found on the prototype chain. + // + // Did you mean "speak"? +} +``` + +**(4)@deprecate (别名@deprecated)** + +deprecate或deprecated修饰器在控制台显示一条警告,表示该方法将废除。 + +```javascript +import { deprecate } from 'core-decorators'; + +class Person { + @deprecate + facepalm() {} + + @deprecate('We stopped facepalming') + facepalmHard() {} + + @deprecate('We stopped facepalming', { url: 'http://knowyourmeme.com/memes/facepalm' }) + facepalmHarder() {} +} + +let person = new Person(); + +person.facepalm(); +// DEPRECATION Person#facepalm: This function will be removed in future versions. + +person.facepalmHard(); +// DEPRECATION Person#facepalmHard: We stopped facepalming + +person.facepalmHarder(); +// DEPRECATION Person#facepalmHarder: We stopped facepalming +// +// See http://knowyourmeme.com/memes/facepalm for more details. +// +``` + +**(5)@suppressWarnings** + +suppressWarnings修饰器抑制decorated修饰器导致的`console.warn()`调用。但是,异步代码出发的调用除外。 + +```javascript +import { suppressWarnings } from 'core-decorators'; + +class Person { + @deprecated + facepalm() {} + + @suppressWarnings + facepalmWithoutWarning() { + this.facepalm(); + } +} + +let person = new Person(); + +person.facepalmWithoutWarning(); +// no warning is logged +``` + +## Mixin + +在修饰器的基础上,可以实现Mixin模式。所谓Mixin模式,就是对象继承的一种替代方案,中文译为“混入”(mix in),意为在一个对象之中混入另外一个对象的方法。 + +请看下面的例子。 + +```javascript +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写成一个修饰器。 + +```javascript +export function mixins(...list) { + return function (target) { + Object.assign(target.prototype, ...list); + }; +} +``` + +然后,就可以使用上面这个修饰器,为类“混入”各种方法。 + +```javascript +import { mixins } from './mixins' + +const Foo = { + foo() { console.log('foo') } +}; + +@mixins(Foo) +class MyClass {} + +let obj = new MyClass(); + +obj.foo() // "foo" +``` + +通过mixins这个修饰器,实现了在MyClass类上面“混入”Foo对象的foo方法。 + +## Trait + +Trait也是一种修饰器,功能与Mixin类型,但是提供更多功能,比如防止同名方法的冲突、排除混入某些方法、为混入的方法起别名等等。 + +下面采用[traits-decorator](https://github.com/CocktailJS/traits-decorator)这个第三方模块作为例子。这个模块提供的traits修饰器,不仅可以接受对象,还可以接受ES6类作为参数。 + +```javascript +import {traits } from 'traits-decorator' + +class TFoo { + foo() { console.log('foo') } +} + +const TBar = { + bar() { console.log('bar') } +} + +@traits(TFoo, TBar) +class MyClass { } + +let obj = new MyClass() +obj.foo() // foo +obj.bar() // bar +``` + +上面代码中,通过traits修饰器,在MyClass类上面“混入”了TFoo类的foo方法和TBar对象的bar方法。 + +Trait不允许“混入”同名方法。 + +```javascript +import {traits } from 'traits-decorator' + +class TFoo { + foo() { console.log('foo') } +} + +const TBar = { + bar() { console.log('bar') }, + foo() { console.log('foo') } +} + +@traits(TFoo, TBar) +class MyClass { } +// 报错 +// throw new Error('Method named: ' + methodName + ' is defined twice.'); +// ^ +// Error: Method named: foo is defined twice. +``` + +上面代码中,TFoo和TBar都有foo方法,结果traits修饰器报错。 + +一种解决方法是排除TBar的foo方法。 + +```javascript +import { traits, excludes } from 'traits-decorator' + +class TFoo { + foo() { console.log('foo') } +} + +const TBar = { + bar() { console.log('bar') }, + foo() { console.log('foo') } +} + +@traits(TFoo, TBar::excludes('foo')) +class MyClass { } + +let obj = new MyClass() +obj.foo() // foo +obj.bar() // bar +``` + +上面代码使用绑定运算符(::)在TBar上排除foo方法,混入时就不会报错了。 + +另一种方法是为TBar的foo方法起一个别名。 + +```javascript +import { traits, alias } from 'traits-decorator' + +class TFoo { + foo() { console.log('foo') } +} + +const TBar = { + bar() { console.log('bar') }, + foo() { console.log('foo') } +} + +@traits(TFoo, TBar::alias({foo: 'aliasFoo'})) +class MyClass { } + +let obj = new MyClass() +obj.foo() // foo +obj.aliasFoo() // foo +obj.bar() // bar +``` + +上面代码为TBar的foo方法起了别名aliasFoo,于是MyClass也可以混入TBar的foo方法了。 + +alias和excludes方法,可以结合起来使用。 + +```javascript +@traits(TExample::excludes('foo','bar')::alias({baz:'exampleBaz'})) +class MyClass {} +``` + +上面代码排除了TExample的foo方法和bar方法,为baz方法起了别名exampleBaz。 + +as方法则为上面的代码提供了另一种写法。 + +```javascript +@traits(TExample::as({excludes:['foo', 'bar'], alias: {baz: 'exampleBaz'}})) +class MyClass {} +``` + +### Babel转码器的支持 + +目前,Babel转码器已经支持Decorator,命令行的用法如下。 + +```bash +$ babel --optional es7.decorators +``` + +脚本中打开的命令如下。 + +```javascript +babel.transfrom("code", {optional: ["es7.decorators"]}) +``` + +Babel的官方网站提供一个[在线转码器](https://babeljs.io/repl/),只要勾选Experimental,就能支持Decorator的在线转码。 diff --git a/sidebar.md b/sidebar.md index 0b50277..9c72668 100644 --- a/sidebar.md +++ b/sidebar.md @@ -22,6 +22,7 @@ 1. [Promise对象](#docs/promise) 1. [异步操作](#docs/async) 1. [Class](#docs/class) +1. [Decorator](#docs/decorator) 1. [Module](#docs/module) 1. [编程风格](#docs/style) 1. [参考链接](#docs/reference)