ES的装饰器

1,078 阅读2分钟

JavaScript中的装饰器

JavaScript中的装饰器是这样的。

@classDecorator
class Person {
	@methodDecorator
	walk () {}
}

Decorators make it possible to annotate and modify classes and properties at design time.

A decorator is:

  • an expression
  • that evaluates to a function
  • that takes the target, name, and decorator descriptor as arguments
  • and optionally returns a decorator descriptor to install on the target object

代码中@ + 函数名JavaScript中的装饰器。装饰器(Decorator)是一种与类(class)相关的语法,用来注释或修改类和类方法。它可以放在类和类方法的定义前面。

JavaScript中的类

JavaScript中的class是这样的。

class Person {
	walk () {
		consolg.log('person can walk.')
	}
}

JavaScript中的class实际上是一个语法糖。

function Person () {}
Object.defineProperty(Person.protorype, 'walk', {
	value: function() { consolg.log('person can walk.') },
    enumerable: false,
    configurable: true,
    writable: true
})

作用于类的装饰器

React中使用Redux时类装饰器十分常见。

import React, { Component } from 'react';
import { connect } from 'react-redux';

@connect(mapStateToProps, mapDispatchToProps)
export default Button extends Component {}

类装饰器就是对整个类进行修饰的。

// 这是ts中对类修饰符的声明
declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
@desc
class Person {}

function desc (target) {
	// 为target上添加一个静态属性
	target.displayName = target.name;
	// 为target添加一个say共享方法
	Object.defineProperty(target.protorype, 'say', {
		value: function() { consolg.log('person can say.') },
	    enumerable: false,
	    configurable: true,
	    writable: true
	})
	return target;
}

对于类装饰器我们可以简单的理解为通过warp对类进行处理,只是该处理是发现在编译阶段而不是在运行时。

class Person {}
function warp (target) {
	// 为target上添加一个静态属性
	target.displayName = target.name;
	// 为target添加一个say共享方法
	Object.defineProperty(target.protorype, 'say', {
		value: function() { consolg.log('person can say.') },
	    enumerable: false,
	    configurable: true,
	    writable: true
	})
	return target;
}
warp(Person);

作用于类方法的装饰器

TypeScript中对类方法修饰器是这么声明的。

declare type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;

JavaScript中是这么对类方法修饰器进行使用的。

function readOnly (target, propertyKey, descriptor) {
	Object.defineProperty(target, propertyKey, {
		...descriptor,
		writable: false
	})
}
class Person {
	@readOnly
	read () {
		console.log('Person can read.');
	}
}

类方法装饰器可以接受三个参数,第二个参数是装饰对象原型(不同于类的装饰,target参数指的是类本身);第二个参数是所要装饰的属性名,第三个参数是该属性的描述对象。