浅谈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

相关文章
相关标签/搜索