Skip to content

ES6学习:装饰器学习笔记

装饰器

安装

npm i babel-plugin-transform-decorators-legacy babel-register --D

transform-decorators-legacy 用于支持装饰器的写法 babel-register 用于接入 node api 能以命令行方式运行

运行方法

  1. 命令行操作

babel --plugins transform-decorators-legacy input.js>input.es5.js

  1. require hook
js
require('babel-register')({
  plugins: ['transform-decorators-legacy']
})
require('./input.js') // 这个文件下有装饰器语法

装饰器用法

js
class Boy {
  @sayName
  say(){}
}
const monkey = new Monkey();
monkey.say();
function sayName(target, key, descriptor){
  descriptor.value = () => {
    console.log("我是XXX");
  }
  console.log("报上名来")
  return descriptor;  
}
//报上名来
//我是XXX
// 装饰器函数yourName 参数固定为这个三个 参照object原型函数
// Object.defineProperty

其实可以想简单点,我是这样理解的。我们通过 const monkey = new Monkey() monkey实例上有了 类上的sayName方法,现在我们执行sayName方法,在这之前会先执行装饰器函数 sayYourName。

monkey.sayName() 应该什么都没对吧,但实际上,sayYourName方法被调用了。同时 装饰器函数可以传递三个参数,分别是 target, key, descriptor

  • target 就是修饰器所在的类, 上面是 Monkey {}
  • key 为修饰器方法的名称 sayYourName
  • descriptor 是一个对象,可与 Object.defineProperty 相比较,我们来打印一下
js
function sayYourName(target, key, descriptor) {
  for (k of Object.keys(descriptor)) {
    console.log(k)
  }
}
  • value 也就是其自身的返回值,这也就是我们能通过装饰器扩展对象属性方法的秘密了
  • writable 设置可写性
  • enumerable 设置可枚举
  • configurable 设置可配置

扩展类

js
class Boy {
  @language('中文')
  say() {
    console.log('hello')
    console.log('I can speak ' + this.language)
  }
}
const fri = new Boy()
fri.say()
function language(lang) {
  return function(target, key, descriptor) {
    target.language = lang
    return descriptor
  }
}

Boy构造函数中并没有 language 属性,但最终我们还是能得到该值,这就是装饰器的功劳了。 通过上述,我们知道了,在执行 fri.say() 时先执行了装饰函数 language,'中文'作为参数传递,target 指向 Boy 构造函数,所以target.language = lang 就是在给 Boy 增加属性

共 20 个模块,1301 篇 Markdown 文档。