es6之装饰器decorator

586 阅读2分钟

什么是装饰器

装饰器(decorator)是一种函数,用于注释或修改类、类方法。写成@ + 函数名

除了注释,装饰器还能用来类型检查。所以,对于类来说,这项功能相当有用。从长期来看,它将是 JavaScript 代码静态分析的重要工具

类的装饰

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

@testable就是一个装饰器,它修改了Foo这个类的行为,为它加上了静态属性isTestable

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

@testable
class Foo{}

console.log(Foo.isTestable);

装饰器还可以传递参数

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

@testable(false)
class Foo{}

注意:装饰器对类的行为的改变,是代码编译时发生的,而不是在运行时。这意味着,装饰器能在编译阶段运行代码。也就是说,装饰器本质就是编译时执行的函数。

方法的装饰

装饰器第一个参数是类的原型对象,第二个参数是所要装饰的属性名,第三个参数是该属性的描述对象

function readonly(target, name, descriptor){
    // descriptor对象原来的值如下
    // {
    //     value: specifiedFunction,
    //     enumerable: false,
    //     configurable: true,
    //     writeable: true,
    // }
    descriptor.writeable = false;
    return descriptor;
}

function log(target, name, descriptor){
    const oldValue = descriptor.value;
    descriptor.value = function () {
        return oldValue.apply(this, arguments);
    }
    return descriptor;
}
class Foo{
    @readonly
    name() {
        return 'this is name';
    }
    @log
    add(a, b) {
        return a + b;
    }
}

// 类似于
Object.defineProperty(Person.prototype, 'name', descriptor);

为什么装饰器不能用于函数

装饰器只能用于类和类的方法,不能用于函数,因为存在函数提升

var counter = 0;

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

@add
function foo() {
}

//
@add
function foo() {
}

var counter;
var add;

counter = 0;

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

总之,由于存在函数提升,使得装饰器不能用于函数。类是不会提升的,所以就没有这方面的问题。

参考链接