详解es6超好用的语法糖Decorator


Posted in Javascript onAugust 01, 2018

Decorator(修饰器/装饰器)是es6提出的语法糖,用于修改类的行为。不过目前主流浏览器都没有很好的支持,我们需要用babel来转换为浏览器能识别的语言。在这篇文章中将介绍decorator的基础用法和一些应用实例。

1.修饰类

(1) 基础用法

@testable
class MyClass{}

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

console.log(MyClass.isTestable) // true

贴一下babel转换后的代码,

var _class;

let MyClass = testable(_class = class MyClass {}) || _class;

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

也可以在prototype上修改属性,也可以为修饰器添加多个参数。

@testable(false)
class MyAnotherClass{
  
}
function testable(status){
  return target=>{target.prototype.isTestable=status}
}
console.log('MyClass.isTestable',MyAnotherClass.prototype.isTestable) // false

当然我们通过修饰器,把某个对象的方法添加到目标类的实例上,注意要在类的prototype上添加。

const foo={isTestable:true}
function testable(...list){
  return target=>{Object.assign(target.prototype,...list)}
}

@testable(foo)
class MyAnotherClass{}
const obj=new MyAnotherClass()

console.log('MyClass.isTestable',obj.isTestable) // true

(2) 应用

React App的开发中,使用redux通常需要react-redux中的connect方法,将两者结合在一起。通常的写法是:

class MyReactComponent extends React.Component {}

export default connect(mapStateToProps, mapDispatchToProps)(MyReactComponent);

如果使用decorator,代码可读性更高了一些。

@connect(mapStateToProps, mapDispatchToProps)
export default class MyReactComponent extends React.Component {}

2.修饰方法

(1).基础用法

// target:在方法中的target指向类的prototype
function readonly(target,key,descriptor){
  descriptor.writable=false
  return descriptor
}

class MyClass{
  @readonly
  print(){console.log(`a:${this.a}`)}
}

(2).js中Object的属性

var person = {}
Object.defineProperty(person,'name',{
  configurable:false,//能否使用delete、能否需改属性特性、或能否修改访问器属性、,false为不可重新定义,默认值为true
  enumerable:false,//对象属性是否可通过for-in循环,flase为不可循环,默认值为true
  writable:false,//对象属性是否可修改,flase为不可修改,默认值为true
  value:'xiaoming' //对象属性的默认值,默认值为undefined
});

对应到descriptor为下面四个属性:

{
   value: specifiedFunction,
   enumerable: false,
   configurable: true,
   writable: true
};

(3). 应用

我们开始写一个@log修饰器,可以输出日志:

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

const math=new Math()
math.add(1,2)

function log(target,name,descriptor){
  const oldValue=descriptor.value

  descriptor.value=function(){
    console.log(`calling ${name} with ${JSON.stringify(arguments)}`)
    return oldValue.apply(this,arguments)
  }

  return descriptor
}

上面的代码中,@log作用是在返回结果前,打印函数名和其参数,起到输出日至的作用。上面的程序运行后,控制台将输出:

calling add with {"0":1,"1":2}

(4). 多个修饰器

良好命名的修饰器可以起到简洁注释的作用,如下:

class Example {
  @readonly
  @enumable
  method(){}
}

多个修饰器的执行顺序是由外向内进入;再由内向外执行。

class Example {
  @decorator(1)
  @decorator(2)
  method(){}
}

function decorator(id){
  console.log('id is ',id)
  return (target,property,descriptor)=>console.log('executed',id)
}

控制台输出

id is  1
id is  2
executed 2
executed 1

附录:babel配置

babel插件transform-decorators还没有正式版,我们可以用transform-decorators-legacy

安装babel

yarn add babel-plugin-transform-decorators-legacy babel-preset-es2017

配置.babelrc

{
  "presets": ["es2017"],
  "plugins":[
    "transform-decorators-legacy"
  ]
}

执行编译后的文件

因为我们为了测试,没必要非得放在浏览器里看了,可以用node执行babel转换后的文件。直接运行yarn start

// package.json

 "scripts": {
  "build": "babel ./decorator -d lib",
  "start":"yarn build && node ./lib/index.js"
 },

参考链接

ECMAScript 6 入门 -- 修饰器

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery validate poshytip 自定义样式
Nov 26 Javascript
用Javascript获取页面元素的具体位置
Dec 09 Javascript
SuperSlide2实现图片滚动特效
Jun 20 Javascript
js数组去重的方法汇总
Jul 29 Javascript
JS实现根据文件字节数返回文件大小的方法
Aug 02 Javascript
基于Bootstrap和jQuery构建前端分页工具实例代码
Nov 23 Javascript
vue如何实现observer和watcher源码解析
Mar 09 Javascript
浅谈js中的this问题
Aug 31 Javascript
深入学习JavaScript中的bom
May 27 Javascript
Vue通过配置WebSocket并实现群聊功能
Dec 31 Javascript
小程序Scroll-view上拉滚动刷新数据
Jun 21 Javascript
详解vue3中组件的非兼容变更
Mar 03 Vue.js
Vue Router去掉url中默认的锚点#
Aug 01 #Javascript
vue定义全局变量和全局方法的方法示例
Aug 01 #Javascript
node.js遍历目录的方法示例
Aug 01 #Javascript
深入浅出理解JavaScript闭包的功能与用法
Aug 01 #Javascript
Angular路由ui-router配置详解
Aug 01 #Javascript
javascript数据结构之多叉树经典操作示例【创建、添加、遍历、移除等】
Aug 01 #Javascript
JavaScript事件冒泡与事件捕获实例分析
Aug 01 #Javascript
You might like
解析在PHP中使用全局变量的几种方法
2013/06/24 PHP
解决安装WampServer时提示缺少msvcr110.dll文件的问题
2017/07/09 PHP
PHP迭代器和生成器用法实例分析
2019/09/28 PHP
javascript学习随笔(使用window和frame)的技巧
2007/03/08 Javascript
?牟┛途W扣了一??效果出?? target=
2007/05/27 Javascript
jquery下利用jsonp跨域访问实现方法
2010/07/29 Javascript
jQuery Tools tab(幻灯片)
2012/07/14 Javascript
点击页面其它地方隐藏该div的两种思路
2013/11/18 Javascript
JS中表单的使用小结
2014/01/11 Javascript
Nodejs学习笔记之Stream模块
2015/01/13 NodeJs
每天一篇javascript学习小结(属性定义方法)
2015/11/19 Javascript
JavaScipt中栈的实现方法
2016/02/17 Javascript
require.js配合插件text.js实现最简单的单页应用程序
2016/07/12 Javascript
解决微信二次分享不显示摘要和图片的问题
2017/08/18 Javascript
jquery鼠标悬停导航下划线滑出效果
2017/09/29 jQuery
vue实现商城购物车功能
2017/11/27 Javascript
react 兄弟组件如何调用对方的方法示例
2018/10/23 Javascript
vue实现鼠标移入移出事件代码实例
2019/03/27 Javascript
vue-cli2与vue-cli3在一台电脑共存的实现方法
2019/09/25 Javascript
详解Vscode中使用Eslint终极配置大全
2019/11/08 Javascript
vue-router重写push方法,解决相同路径跳转报错问题
2020/08/07 Javascript
Electron+vue从零开始打造一个本地播放器的方法示例
2020/10/27 Javascript
nuxt静态部署打包相对路径操作
2020/11/06 Javascript
[04:59]2018DOTA2亚洲邀请赛 4.7 Mineski夺冠时刻
2018/04/09 DOTA
Python使用matplotlib绘图无法显示中文问题的解决方法
2018/03/14 Python
Django中STATIC_ROOT和STATIC_URL及STATICFILES_DIRS浅析
2018/05/08 Python
在python中使用xlrd获取合并单元格的方法
2018/12/26 Python
python 根据时间来生成唯一的字符串方法
2019/01/14 Python
咖啡为什么会有酸味?你喝到的咖啡為什麼是酸的?
2021/03/17 冲泡冲煮
css3 background属性调整增强介绍
2010/12/18 HTML / CSS
伦敦新晋轻奢耳饰潮牌:Tada & Toy
2020/05/25 全球购物
.net笔试题
2014/03/03 面试题
最新奶茶店创业计划书范文
2014/02/08 职场文书
2015年五一劳动节活动总结
2015/02/09 职场文书
中考百日冲刺决心书
2015/09/22 职场文书
Win10此设备不支持接收Miracast无法投影的解决方法
2022/07/07 数码科技