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

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