淺談ES7的修飾器

類的修飾

許多面向對象的語言都有修飾起函數,用來修改類的行爲函數

@testable
class MyTestableClass{
    
}

function testable(target){
    target.isTestable = true
}

MyTestableClass.isTestable  // true
複製代碼

上面代碼中,@testable就是修飾器。它修改了MyTestableClass這個類的行爲,爲它加上了靜態屬性isTestable。testable函數的參數target是MyTestableClass類自己。也就是說,修飾器是一個對類進行處理的函數。修飾器函數的第一個參數,就是所要修飾的目標類ui

若是以爲一個參數不夠用,能夠在修飾器外面再封裝一層函數this

function testable(isTestable){
    return function(target){
        target.isTestable = isTestable
    }
}

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

@testable(false)
class MyTestableClass{}
MyTestableClass.isTestable  // false
複製代碼

修飾器對類的行爲的改變,是代碼編譯時發生的,而不是在運行時。lua

若是想添加實例屬性,能夠經過目標類的prototype對象操做spa

function testable(target){
    target.prototype.isTestable = true
}

@testable
class MyTestableClass{}

let obj = new MyTestableClass();
obj.isTestable  // true
複製代碼

方法的修飾

修飾器不只能夠修飾類,還能夠修飾類的屬性prototype

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

修飾器readonly用來修飾 類 的name方法,修飾器readonly一共能夠接受三個參數。code

function readonly(target, name, descriptor){
    // descriptor對象原來的值以下
  // {
  // value: specifiedFunction,
  // enumerable: false,
  // configurable: true,
  // writable: true
  // };
  descriptor.writable = false;
  return descriptor;
}

readonly(Person.prototype, 'name', descriptor)
複製代碼

修飾器第一個參數是類的原型對象,上例是Person.prototype,修飾器的本意是要 修飾類的實例,可是這個實例尚未生成,因此智能去修飾原型,第二個參數是所要修飾的屬性名,第三個參數是該屬性的描述對象。對象

多個修飾器的執行

function dec(id){
	// 此處是按照修飾順序執行
    console.log('evaluated', id);
    // 返回的函數則是按照反順序執行。
    return (target, property, descriptor) => console.log('executed', id)
}

class Example{
    @dec(1)
    @dec(2)
   	method(){}
}
// evaluated 1
// evaluated 2
// executed 2
// executed 1
複製代碼

若是同一個方法有多個修飾器,會像剝洋蔥同樣,先從外到內進入,而後由內向外執行。ip

外層修飾器@dec(1)先進入,可是內層修飾器@dec(2)先執行。ci

相關文章
相關標籤/搜索