详解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 相关文章推荐
JAVASCRIPT HashTable
Jan 22 Javascript
JQuery实现的在新窗口打开链接的方法小结
Apr 22 Javascript
extjs grid设置某列背景颜色和字体颜色的实现方法
Sep 06 Javascript
有趣的JavaScript数组长度问题代码说明
Jan 20 Javascript
基于jQuery的动态表格插件
Mar 28 Javascript
Jquery实现鼠标移上弹出提示框、移出消失思路及代码
May 19 Javascript
巧用jquery解决下拉菜单被Div遮挡的相关问题
Feb 13 Javascript
AngularJS基础 ng-show 指令简单示例
Aug 03 Javascript
Vue.js自定义指令的用法与实例解析
Jan 18 Javascript
详解angular2实现ng2-router 路由和嵌套路由
Mar 24 Javascript
vue实现二级导航栏效果
Oct 19 Javascript
解决vue无法侦听数组及对象属性的变化问题
Jul 17 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
php中用socket模拟http中post或者get提交数据的示例代码
2013/08/08 PHP
thinkphp实现面包屑导航(当前位置)例子分享
2014/05/10 PHP
php switch语句多个值匹配同一代码块应用示例
2014/07/29 PHP
php实现图片转换成ASCII码的方法
2015/04/03 PHP
PHP内存缓存功能memcached示例
2016/10/19 PHP
PHP递归实现快速排序的方法示例
2017/12/18 PHP
php原生数据库分页的代码实例
2019/02/18 PHP
Laravel自定义 封装便捷返回Json数据格式的引用方法
2019/09/29 PHP
laravel-admin select框默认选中的方法
2019/10/03 PHP
用javascript实现无刷新更新数据的详细步骤 asp
2006/12/26 Javascript
Json和Jsonp理论实例代码详解
2013/11/15 Javascript
js清除input中type等于file的值域(示例代码)
2013/12/24 Javascript
js中replace的用法总结
2013/12/27 Javascript
jQuery之ajax删除详解
2014/02/27 Javascript
使用JavaScript开发IE浏览器本地插件实例
2015/02/18 Javascript
ECMAScript 5严格模式(Strict Mode)介绍
2015/03/02 Javascript
详解angular element()方法使用
2017/04/08 Javascript
Vue上传组件vue Simple Uploader的用法示例
2017/08/25 Javascript
Vue2 SSR渲染根据不同页面修改 meta
2017/11/20 Javascript
Vue实现表格中对数据进行转换、处理的方法
2018/09/06 Javascript
JavaScript实现简单进度条效果
2020/03/25 Javascript
前端 javascript 实现文件下载的示例
2020/11/24 Javascript
Python爬虫 bilibili视频弹幕提取过程详解
2019/07/31 Python
python对XML文件的操作实现代码
2020/03/27 Python
如何完美的建立一个python项目
2020/10/09 Python
详解tensorflow之过拟合问题实战
2020/11/01 Python
Python之京东商品秒杀的实现示例
2021/01/06 Python
Wilson体育用品官网:美国著名运动器材品牌
2019/05/12 全球购物
澳大利亚100%丝绸多彩度假装商店:TheSwankStore
2019/09/04 全球购物
优秀的毕业生的自我评价
2013/12/12 职场文书
会计主管岗位职责
2014/01/03 职场文书
2014年教育教学工作总结
2014/11/13 职场文书
李强为自己工作观后感
2015/06/11 职场文书
教师节座谈会主持词
2015/07/03 职场文书
承诺书应该怎么写?
2019/09/10 职场文书
redis复制有可能碰到的问题汇总
2022/04/03 Redis