详解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增加join方法的实现代码
Nov 28 Javascript
Jquery中val()表单取值赋值的实例代码
Aug 15 Javascript
javascript中Number对象的toString()方法分析
Dec 20 Javascript
浅析javascript 定时器
Dec 23 Javascript
JQuery查找DOM节点的方法
Jun 11 Javascript
详解JavaScript中数组的相关知识
Jul 29 Javascript
基于JS实现导航条之调用网页助手小精灵的方法
Jun 17 Javascript
JavaScript程序中实现继承特性的方式总结
Jun 24 Javascript
AngularJS 指令详细介绍
Jul 27 Javascript
微信小程序 利用css实现遮罩效果实例详解
Jan 21 Javascript
JS使用正则表达式验证身份证号码
Jun 23 Javascript
Vue 实现从文件中获取文本信息的方法详解
Oct 16 Javascript
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
ajax php 实现写入数据库
2009/09/02 PHP
php与flash as3 socket通信传送文件实现代码
2014/08/16 PHP
php实现约瑟夫问题的方法小结
2015/03/23 PHP
PHP实现的各类hash算法长度及性能测试实例
2017/08/27 PHP
解决Laravel 不能创建 migration 的问题
2019/10/09 PHP
Yii框架getter与setter方法功能与用法分析
2019/10/22 PHP
js 获取子节点函数 (兼容FF与IE)
2010/04/18 Javascript
js限制文本框为整数和货币的函数代码
2010/10/13 Javascript
js限制input标签中只能输入中文
2015/06/26 Javascript
jQuery与getJson结合的用法实例
2015/08/07 Javascript
[Bootstrap-插件使用]Jcrop+fileinput组合实现头像上传功能实例代码
2016/12/20 Javascript
vue升级之路之vue-router的使用教程
2018/08/14 Javascript
vue环形进度条组件实例应用
2018/10/10 Javascript
基于JS判断对象是否是数组
2020/01/10 Javascript
JS document对象简单用法完整示例
2020/01/14 Javascript
Ant Design moment对象和字符串之间的相互转化教程
2020/10/27 Javascript
[01:25]2015国际邀请赛最佳短片奖——斧王《拆塔英雄:天赋异禀》
2015/09/22 DOTA
python排序方法实例分析
2015/04/30 Python
django上传图片并生成缩略图方法示例
2017/12/11 Python
Python获取指定文件夹下的文件名的方法
2018/02/06 Python
python学习基础之循环import及import过程
2018/04/22 Python
网易有道2017内推编程题 洗牌(python)
2019/06/19 Python
python实现的按要求生成手机号功能示例
2019/10/08 Python
关于Python 常用获取元素 Driver 总结
2019/11/24 Python
python的链表基础知识点
2020/09/13 Python
python Scrapy爬虫框架的使用
2021/01/21 Python
CSS3实现圆角、阴影、透明效果并兼容各大浏览器
2014/08/08 HTML / CSS
HTML5 DeviceOrientation实现手机网站摇一摇功能代码实例
2015/04/24 HTML / CSS
罗马尼亚在线杂货店:Pilulka.ro
2019/09/28 全球购物
linux面试题参考答案(9)
2016/01/29 面试题
信息专业本科生个人的自我评价
2013/10/28 职场文书
党支部活动策划方案
2014/08/18 职场文书
村创先争优活动总结
2014/08/28 职场文书
甜品店创业计划书
2014/09/21 职场文书
小学见习报告
2014/10/31 职场文书
学期个人自我总结
2015/02/13 职场文书