ES6之decorator

ES6的decorator相信大家都听说过,但是用的可能会比较少,今天就一起来看一下这个decorator是干嘛的

装饰器(decorator)是一种与类相关的语法,用来注释或修改类和类的方法

装饰器是一种函数,使用@+函数名的写法,它可以放在类和类方法的定义前面

1 类的装饰器

装饰器可以用来修饰整个类

@testable
class MyTestableClass {
  // ...
}

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

MyTestableClass.isTestable // true

上面的代码中,@testable是一个装饰器,修饰了MyTestableClass这个类,testable是一个函数,具体实现是如何修饰这个类的,修饰的内容是给类增加了isTestable这个**静态属性**

装饰器的行为如下:

@decorator
class A {}

A = decorator(A) || A

也就是说,装饰器是一个对类进行处理的函数,这个函数可以传参,也可以被多层封装,外层的参数为传递的参数,最内层的参数为修饰的类对象

function testable(isTestable) {
	return function(target) {
		target.isTestable = isTestable
	}
}
@testable(true)
class MyTestClass {
}

MyTestClass.isTestable // true

装饰器是在编译阶段就会执行的
上面代码是为类添加静态属性,下面的代码则是为一个类添加实例属性

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

let mt = new MyTestable
mt.isTestable //true

现在有一个场景,需要将一个对象的方法添加到一个类里,传统的方法,使用Object.assign

const Foo = {
	foo() {
		console.log('foo')
	}
}

class MyClass {}

Object.assign(MyClass.prototype, Foo)

现在有了装饰器,我们也可以这么写

function testable(obj) {
	return function (target) {
		Object.assign(target.prototype, obj)
	}
}

@testable(Foo)
MyClass{}

let obj = new MyClass
obj.foo() // 'foo'

2 方法的装饰

修饰一个方法例子:

class Person {
  @nonconfig
  kidCount() { return 12 }
}

function nonconfig(target, name, descriptor) {
  descriptor.configurable = false;
  return descriptor;
}

console.log(Object.getOwnPropertyDescriptor(Person.prototype, 'kidCount'))

再看下面一个例子,可以打印日志

class Math {
  @log
  add(a, b) {
    return a + b
  }
}

function log (target, name, descirptor) {
  var oldValue = descirptor.value
  descirptor.value = function() {
    console.log(`Calling ${name} with ` , arguments)
    return oldValue.apply(this, arguments)
  }
  return descirptor
}
const math = new Math
math.add(1, 2) // Calling add with  Arguments(2)

3 core-decorators.js

core-decorators.js是一个第三方的模块,提供了常见的装饰器,可以直接使用
1、autobind使得方法中的this对象,绑定原始对象

import { autobind } from 'core-decorators';

class Person {
  @autobind
  getPerson() {
    return this;
  }
}

let person = new Person();
let getPerson = person.getPerson;

getPerson() === person;
// true

上面代码中如果不加@autobind,则getPerson返回一个undefined,原因是环境处于严格模式,非严格模式应该是window

2、readonly,修饰类里的属性,为只读模式

import { readonly } from 'core-decorators'

class Meal {
  @readonly
  entree = 'steak'
}

let m = new Meal
m.entree = 'salmon' 
// Uncaught TypeError: Cannot assign to read only property 'entree' of object

3、override检查子类的方法,是否覆盖父类的方法

import { override } from 'core-decorators'

class Parent {
  speak (first, last) {}
}

class Child extends Parent {
  @override
  speak() {} //Uncaught SyntaxError: Child#speak() does not properly override Parent#speak(first, last)
}

上面代码中,子类的方法缺少两个参数

4、deprecate显示一条警告,表示该方法将废除

import { deprecate } from 'core-decorators';

class Person {
  @deprecate
  facepalm() {}

  @deprecate('We stopped facepalming')
  facepalmHard() {}

  @deprecate('We stopped facepalming', { url: 'http://knowyourmeme.com/memes/facepalm' })
  facepalmHarder() {}
}

let person = new Person();

person.facepalm();
// DEPRECATION Person#facepalm: This function will be removed in future versions.

person.facepalmHard();
// DEPRECATION Person#facepalmHard: We stopped facepalming

person.facepalmHarder();
// DEPRECATION Person#facepalmHarder: We stopped facepalming
//
//     See http://knowyourmeme.com/memes/facepalm for more details.
//
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值