其他分享
首页 > 其他分享> > ECMAScript 6-修饰器Decorator

ECMAScript 6-修饰器Decorator

作者:互联网

修饰器(Decorator)是一个函数,用来修改类的行为。修饰器对类的行为的改变,是代码编译时发生的,而不是在运行时。这意味着,修饰器能在编译阶段运行代码

在这里插入图片描述

类的修饰

//修饰器函数1:为类加上静态属性isTestable
//修饰器函数的第一个参数,就是所要修饰的目标类
function testable(target) {
  target.isTestable = true;
}

//修饰类的行为。写在类上方,表示修饰器的目标是这整个类
@testable
class MyTestableClass {}

console.log(MyTestableClass.isTestable) // true
//修饰器函数2:添加实例属性
function testable(target) {
  target.prototype.isTestable = true;
}

@testable
class MyTestableClass {}

let obj = new MyTestableClass();
obj.isTestable // true

修饰器的实际行为

@decorator
class A {}

// 等同于
class A {}
A = decorator(A) || A;

类的方法的修饰

class Person {
  @readonly
  name() { return `${this.first} ${this.last}` }
}

修饰器的参数

修饰器函数一共可以接受三个参数:

function nonenumerable(target, name, descriptor) {
  descriptor.enumerable = false; //修改了描述对象的属性enumerable,使得不可遍历
  return descriptor;
}

class Person {
  @nonenumerable //修饰该属性
  get kidCount() { return this.children.length; }
}

@log修饰器例子:输出日志

function log(target, name, descriptor) {
  var oldValue = descriptor.value;
  descriptor.value = function() {
    console.log(`Calling "${name}" with`, arguments);
    return oldValue.apply(null, arguments);
  };
  return descriptor;
}

class Math {
  @log
  add(a, b) {
    return a + b;
  }
}


const math = new Math();
// passed parameters should get logged now
math.add(2, 4);

修饰器有注释作用

@testable
class Person {
  @readonly
  @nonenumerable
  name() { return `${this.first} ${this.last}` }
}
//可看出Person类是可测试的,而name方法是只读和不可枚举的

core-decorators.js

core-decorators.js是一个第三方模块,提供了几个常见的修饰器,通过它可以更好地理解修饰器

Mixin

在修饰器的基础上,可以实现Mixin模式。所谓Mixin模式,就是对象继承的一种替代方案,中文译为“混入”(mixin),意为在一个对象之中混入另外一个对象的方法

以往写法:

//一个对象,里面有个foo方法
const Foo = {
  foo() { console.log('foo') }
};

//一个类
class MyClass {}

//通过Object.assign在类的原型对象上添加Foo对象上的方法添加进去,
Object.assign(MyClass.prototype, Foo);

let obj = new MyClass();
obj.foo() // '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) //传入Foo对象,把Foo对象中foo方法的添加在MyClass的原型对象中
class MyClass {}

let obj = new MyClass();
obj.foo() // "foo"

Trait修饰器

效果与Mixin类似,但是提供更多功能,比如防止同名方法的冲突、排除混入某些方法、为混入的方法起别名等等

下面采用traits-decorator这个第三方模块作为例子。这个模块提供的traits修饰器,不仅可以接受对象,还可以接受ES6类作为参数

import { traits } from 'traits-decorator';

//TFoo类中有foo方法
class TFoo {
  foo() { console.log('foo') }
}

//TBar对象中有bar方法
const TBar = {
  bar() { console.log('bar') }
};

//把TFoo类中有foo方法和TBar对象中有bar方法加进MyClass类的原型对象中
@traits(TFoo, TBar)
class MyClass { }

let obj = new MyClass();
obj.foo() // foo
obj.bar() // bar

另外,Trait不允许“混入”同名方法

Babel转码器的支持

目前,Babel转码器已经支持Decorator。

首先,安装babel-corebabel-plugin-transform-decorators。由于后者包括在babel-preset-stage-0之中,所以改为安装babel-preset-stage-0亦可

$ npm install babel-core babel-plugin-transform-decorators

然后,设置配置文件.babelrc

{
  "plugins": ["transform-decorators"]
}

这时,Babel就可以对Decorator转码了

脚本中打开的命令如下

babel.transform("code", {plugins: ["transform-decorators"]})

标签:对象,Person,ECMAScript,修饰,foo,decorators,class,Decorator
来源: https://www.cnblogs.com/sanhuamao/p/13595816.html