详解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 相关文章推荐
js弹出层包含flash 不能关闭隐藏的2种处理方法
Jun 17 Javascript
Jquery的hide及toggle方法让超链接慢慢消失
Sep 06 Javascript
一个js控制的导航菜单实例代码
Dec 03 Javascript
node.js中的url.format方法使用说明
Dec 10 Javascript
DOM基础教程之使用DOM设置文本框
Jan 20 Javascript
JavaScript判断是否为数字的4种方法及效率比较
Apr 01 Javascript
jQuery跨域问题解决方案
Aug 03 Javascript
js图片跟随鼠标移动代码
Nov 26 Javascript
H5用户注册表单页 注册模态框!
Sep 17 Javascript
Javascript中 带名 匿名 箭头函数的重要区别(推荐)
Jan 29 Javascript
基于Nuxt.js项目的服务端性能优化与错误检测(容错处理)
Oct 23 Javascript
Vue $attrs & inheritAttr实现button禁用效果案例
Dec 07 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运算符的知识大全
2011/11/03 PHP
div li的多行多列 无刷新分页示例代码
2013/10/16 PHP
php统计时间和内存使用情况示例分享
2014/03/13 PHP
mac下Apache + MySql + PHP搭建网站开发环境
2014/06/02 PHP
laravel5创建service provider和facade的方法详解
2016/07/26 PHP
PHP排序算法之希尔排序(Shell Sort)实例分析
2018/04/20 PHP
PHP序列化的四种实现方法与横向对比
2018/11/29 PHP
PHP类与对象后期静态绑定操作实例详解
2018/12/20 PHP
基于PHP+mysql实现新闻发布系统的开发
2020/08/06 PHP
用js实现层随着内容大小动态渐变改变 推荐
2009/12/19 Javascript
jQuery代码优化 遍历篇
2011/11/01 Javascript
杨氏矩阵查找的JS代码
2013/03/21 Javascript
JavaScript阻止浏览器返回按钮的方法
2015/03/18 Javascript
javascript消除window.close()的提示窗口
2015/05/20 Javascript
JavaScript中的对象继承关系
2016/08/01 Javascript
jQuery EasyUI编辑DataGrid用combobox实现多级联动
2016/08/29 Javascript
利用jQuery解析获取JSON数据
2017/04/08 jQuery
bootstrap模态框远程示例代码分享
2017/05/22 Javascript
jQuery、layer实现弹出层的打开、关闭功能
2017/06/28 jQuery
Vue仿今日头条实例详解
2018/02/06 Javascript
一个手写的vue放大镜效果
2019/08/09 Javascript
windows下create-react-app 升级至3.3.1版本踩坑记
2020/02/17 Javascript
python获取网页状态码示例
2014/03/30 Python
python中MySQLdb模块用法实例
2014/11/10 Python
Python 创建子进程模块subprocess详解
2015/04/08 Python
python pygame实现五子棋小游戏
2020/10/26 Python
python实现逆滤波与维纳滤波示例
2020/02/26 Python
python对数组进行排序,并输出排序后对应的索引值方式
2020/02/28 Python
python 代码运行时间获取方式详解
2020/09/18 Python
css背景图片的背景裁切、背景透明度、背景变换等效果运用
2012/12/24 HTML / CSS
CSS3属性background-size使用指南
2014/12/09 HTML / CSS
Fabletics官网:美国运动服饰品牌,由好莱坞女演员凯特·哈德森创立
2019/10/19 全球购物
生产车间主管岗位职责
2013/12/28 职场文书
班子成员四风问题自我剖析材料
2014/09/29 职场文书
2015年世界水日活动总结
2015/02/09 职场文书
酒店服务员岗位职责
2015/02/09 职场文书