本文共 3223 字,大约阅读时间需要 10 分钟。
为对象添加新功能
不改变其原有的结构和功能
传统 UML 类图
简化后的 UML 类图
class Circle{ draw() { console.log('画一个圆形') }}class Decorator { constructor(circle) { this.circle = circle } draw() { this.circle.draw() this.setRedBorder(circle) } setRedBorder(circle) { console.log('设置红色边框') }}// 测试let circle = new Circle()circle.draw()let dec = new Decorator(circle)dec.draw()
配置环境,安装插件
npm install babel-plugin-transform-decorators-legacy --save-dev
.babelrc 文件
{ "presets": ["es2015", "latest"], "plugins": ["transform-decorators-legacy"]}
验证环境
@testDec // 装饰器class Demo { // ...}function testDec(target) { // target 其实就是 class Demo target.isDec = true}alert(Demo.isDec) // true
装饰类
// 装饰器的原理@decoratorclass A { }// 等同于class A { }A = decorator(A) || A;
// 可以加参数function testDec(isDec) { return function(target) { target.isDec = isDec; }}@testDec(true)class Demo { // ...}alert(Demo.isDec) // true
装饰类 - mixin 示例
function mixins(...list) { return function (target) { Object.assign(target.prototype, ...list) }}const Foo = { foo() { alert('foo') }}@mixins(Foo)class MyClass { }let obj = new MyClass();obj.foo() // 'foo'
装饰方法 - 例1
class Person { constructor() { this.first = 'A' this.last = 'B' } // 装饰方法 @readonly name() { return `${ this.first} ${ this.last}` }}var p = new Persion()console.log(p.name())// p.name = function () {} // 这里会报错,因为 name 是只读属性
readonly 如何实现的
function readonly(target, name, descriptor) { // descriptor 属性描述对象 (Object.defineProperty 中会用到), 原来的值如下 // { // value: specifiedFunction, // enumerabel: false, // configurable: true, // writable: true, // }; descriptor.writable = false; // 关闭可写 return descriptor;}
装饰方法 - 例2
class Math { // 装饰方法 @log add(a, b) { return a + b; }}const math = new Math();const result = math.add(2, 4); // 执行 add 时,会自动打印日志,因为有 @log 装饰器console.log('result', result);
log 如何实现的
function log(target, name, descriptor) { var oldValue = descriptor.value; descriptor.value = function() { console.log(`Calling ${ name} with`, arguments); return oldValue.apply(this, arguments); }; return descriptor;}
第三方开源 lib
提供常用的装饰器
查阅文档
:示例
// 首先安装 npm install core-decorators --save// 开始编码import { readonly } from 'core-decorators'class Person { @readonly name() { return 'zhang' }}let p = new Person()alert(p.name())p.name = function () { /*...*/ } // 此处会报错
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 facepalmingperson.facepalmHarder();// DEPRECATION Person#facepalmHarder: We stopped facepalming// See http://knowyourmeme.com/memes/facepalm for more details.
将现有对象和装饰器进行分离,两者独立存在
符合开放封闭原则
转载地址:http://qcqwi.baihongyu.com/