详解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 相关文章推荐
struts2+jquery+json实现异步加载数据(自写)
Jun 24 Javascript
火狐textarea输入法的bug的触发及解决
Jul 24 Javascript
javascript单引号和双引号的区别和处理
May 14 Javascript
JavaScript italics方法入门实例(把字符串显示为斜体)
Oct 17 Javascript
js QQ客服悬浮效果实现代码
Dec 12 Javascript
jQuery实现右下角可缩放大小的层完整实例
Jun 20 Javascript
JS日程管理插件FullCalendar中文说明文档
Feb 06 Javascript
JS利用cookies设置每隔24小时弹出框
Apr 20 Javascript
Vee-Validate的使用方法详解
Sep 22 Javascript
AngularJs用户登录问题处理(交互及验证、阻止FQ处理)
Oct 26 Javascript
如何换个角度使用VUE过滤器详解
Sep 11 Javascript
jquery实现抽奖功能
Oct 22 jQuery
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操作Access类(PHP+ODBC+Access)
2007/01/02 PHP
PHP IDE phpstorm 常用快捷键
2015/05/18 PHP
PHP 实现人民币小写转换成大写的方法及大小写转换函数
2017/11/17 PHP
tp5修改(实现即点即改)
2019/10/18 PHP
Prototype1.5 rc2版指南最后一篇之Position
2007/01/10 Javascript
学习jquery必备 api中英文对照的chm手册 下载
2007/05/03 Javascript
关于scrollLeft,scrollTop的浏览器兼容性测试
2013/03/19 Javascript
js history对象简单实现返回和前进
2013/10/30 Javascript
jQuery中first()方法用法实例
2015/01/06 Javascript
jQuery定义背景动态切换效果的方法
2015/03/23 Javascript
jQuery实现平滑滚动的标签分栏切换效果
2015/08/28 Javascript
Javascript实现图片轮播效果(二)图片序列节点的控制实现
2016/02/17 Javascript
AngularJs实现分页功能不带省略号的代码
2016/05/30 Javascript
全面了解addEventListener和on的区别
2016/07/14 Javascript
JavaScript数组去重由慢到快由繁到简(优化篇)
2016/08/26 Javascript
Vue中render方法的使用详解
2018/01/26 Javascript
3种vue路由传参的基本模式
2018/02/22 Javascript
微信小程序简单的canvas裁剪图片功能详解
2019/07/12 Javascript
对python中执行DOS命令的3种方法总结
2018/05/12 Python
PyCharm+Pipenv虚拟环境开发和依赖管理的教程详解
2020/04/16 Python
Python中Pyspider爬虫框架的基本使用详解
2021/01/27 Python
解决pycharm 格式报错tabs和space不一致问题
2021/02/26 Python
CSS3轻松实现清新 Loading 效果的简单实例
2016/06/06 HTML / CSS
Expedia马来西亚旅游网站:廉价酒店,度假村和航班预订
2016/07/26 全球购物
美国东北部户外服装和设备零售商:Eastern Mountain Sports
2016/10/05 全球购物
英文自我鉴定
2013/12/10 职场文书
医生进修自我鉴定
2014/01/19 职场文书
户外用品商店创业计划书
2014/01/29 职场文书
国家励志奖学金个人先进事迹材料
2014/05/04 职场文书
选秀节目策划方案
2014/06/06 职场文书
三八节标语
2014/06/27 职场文书
工厂仓管员岗位职责范本
2014/07/17 职场文书
八荣八耻的活动方案
2014/08/16 职场文书
2015年乡镇信访工作总结
2015/04/07 职场文书
2015年中秋节主持词
2015/07/30 职场文书
SpringBoot实现异步事件驱动的方法
2021/06/28 Java/Android