详解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 相关文章推荐
页面只有一个text的时候,回车自动submit的解决方法
Aug 12 Javascript
获取内联和链接中的样式(js代码)
Apr 11 Javascript
jquery为页面增加快捷键示例
Jan 31 Javascript
JavaScript中的console.assert()函数介绍
Dec 29 Javascript
DOM操作一些常用的属性汇总
Mar 13 Javascript
详解vue数据渲染出现闪烁问题
Jun 29 Javascript
JavaScript 值类型和引用类型的初次研究(推荐)
Jul 19 Javascript
玩转vue的slot内容分发
Sep 22 Javascript
vue+element+Java实现批量删除功能
Apr 08 Javascript
vue使用keep-alive实现组件切换时保存原组件数据方法
Oct 30 Javascript
Array.filter中如何正确使用Async
Nov 04 Javascript
vue 把二维或多维数组转一维数组
Apr 24 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序列号生成函数和字符串替换函数代码
2012/06/07 PHP
php读取3389的脚本
2014/05/06 PHP
CentOS 6.3下安装PHP xcache扩展模块笔记
2014/09/10 PHP
PHP进行批量任务处理不超时的解决方法
2016/07/11 PHP
Laravel 数据库加密及数据库表前缀配置方法
2019/10/10 PHP
js停止输出代码
2008/07/20 Javascript
jquery URL参数判断,确定菜单样式
2010/05/31 Javascript
基于Jquery的文字自动截取(提供源代码)
2011/08/09 Javascript
Array栈方法和队列方法的特点说明
2014/01/24 Javascript
JavaScript使用FileSystemObject对象写入文本文件内容的方法
2015/08/05 Javascript
web 前端常用组件之Layer弹出层组件
2016/09/22 Javascript
Javascript中字符串replace方法的第二个参数探究
2016/12/05 Javascript
ionic实现底部分享功能
2017/05/11 Javascript
微信小程序使用modal组件弹出对话框功能示例
2017/11/29 Javascript
vue vuex vue-rouert后台项目——权限路由(适合初学)
2017/12/29 Javascript
vue component 中引入less文件报错 Module build failed
2019/04/17 Javascript
vue-cli3配置与跨域处理方法
2019/08/17 Javascript
JS数据类型STRING使用实例解析
2019/12/18 Javascript
Python修改MP3文件的方法
2015/06/15 Python
简单学习Python time模块
2016/04/29 Python
在Python中Dataframe通过print输出多行时显示省略号的实例
2018/12/22 Python
python 实现UTC时间加减的方法
2018/12/31 Python
Python+OpenCV实现图像的全景拼接
2020/03/05 Python
在vscode中启动conda虚拟环境的思路详解
2020/12/25 Python
现代生活方式的家具和装饰:Dot & Bo
2018/12/26 全球购物
高级运动鞋:GREATS
2019/07/19 全球购物
Eton丹麦官网:精美的男式衬衫
2020/05/27 全球购物
店长职务说明书
2014/02/04 职场文书
《雨点儿》教学反思
2014/04/14 职场文书
产品生产计划书
2014/05/07 职场文书
大足石刻导游词
2015/02/02 职场文书
结婚保证书(三从四德)
2015/02/26 职场文书
幼儿园开学家长寄语(2016春季)
2015/12/03 职场文书
职业生涯规划书之大学四年
2019/08/07 职场文书
幽默口才训练经典句子(48句)
2019/08/19 职场文书
JavaScript架构搭建前端监控如何采集异常数据
2022/06/25 Javascript