decorator(装饰器)总结及第三方包介绍

decorator作为一个提案,经过了多次修改,还未正式发布,不过在实际编程过程中,装饰器已经有了很多的应用。装饰器很受欢迎的主要原因是其借鉴了java中注解的概念,让代码结构性和可读性大大增强。

装饰器的意义:更好地解释类的相关属性和概念,将不同的功能归类区分,便于维护和扩展。

demo:

@Component({
  tag: 'my-component',
  styleUrl: 'my-component.scss'
})
export class MyComponent {
  @Prop() first: string;
  @Prop() last: string;
  @State() isVisible: boolean = true;

  render() {
    return (
      <p>Hello, my name is {this.first} {this.last}</p>
    );
  }
}

上面的代码很好的看出当前类的一些介绍。

装饰器的分类:

1,类的装饰 (接受参数target)

语法:

function testable(target) {
  //doSomething
}

@testable
class MyTestableClass {}

2,方法的装饰

function readonly(target, name, descriptor){ //这里的target不同于类的装饰,指的是要装饰类的prototype
  // descriptor对象原来的值如下
  // {
  //   value: specifiedFunction,
  //   enumerable: false,
  //   configurable: true,
  //   writable: true
  // };
  descriptor.writable = false;
  return descriptor;
}

说明:方法装饰器的target不同于类的装饰,指的是要装饰类的

实例:

class Person {
  @nonenumerable
  get kidCount() { return this.children.length; }
}

function nonenumerable(target, name, descriptor) {
  console.log(target)
  descriptor.enumerable = false;
  return descriptor;
}

装饰器的高级用法:

从装饰器的使用上可以看出,在使用装饰器时,并没有直接执行装饰器,只是指定装饰器,因此装饰器可以写成高阶函数的形式,在函数里返回一个装饰器。在指定装饰器时直接执行外层函数,返回一个待执行的装饰器。

实例:

//类的装饰器
function testable(isTestable) {
  return function(target) {
    target.isTestable = isTestable;
  }
}

@testable(true)
class MyTestableClass {}
MyTestableClass.isTestable // true

@testable(false)
class MyClass {}
MyClass.isTestable // false



//方法装饰器
function dec(id){
  console.log('evaluated', id);
  return (target, property, descriptor) => console.log('executed', id);
}

class Example {
    @dec(1)
    @dec(2)
    method(){}
}

一个很重要的注意事项:

装饰器不能用于函数,因为函数存在提升。(存在函数提升的原因是js解释器在对js代码进行词法分析时,会先去进行函数的定义,对于函数表达式不会存在变量提升也是基于该原因,具体可以去研究js执行上下文队列的相关知识)

实例:

var counter = 0;

var add = function () {
  counter++;
};

@add
function foo() {
}

实际上运行时:(上下文入栈顺序)

@add
function foo() {
}

var counter;
var add;

counter = 0;

add = function () {
  counter++;
};

mixin

自定义的混入对象方法的函数,可以根据实际业务场景进行封装。

比如:

export function mixins(...list) {
  return function (target) {
    Object.assign(target.prototype, ...list);
  };
}

几个重要的库:

1,core-decorators.js

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

比如:@readonly 

import { readonly } from 'core-decorators';

class Meal {
  @readonly
  entree = 'steak';
}

var dinner = new Meal();
dinner.entree = 'salmon';

2,Trait 

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

实例:

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

 

参考:http://es6.ruanyifeng.com/#docs/decorator#Trait

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章