详解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 打开页面window.location和window.open的区别
Mar 17 Javascript
如何书写高质量jQuery代码(使用jquery性能问题)
Jun 30 Javascript
jquery实现隐藏在左侧的弹性弹出菜单效果
Sep 18 Javascript
全屏js头像上传插件源码高清版
Mar 29 Javascript
JS中使用DOM来控制HTML元素
Jul 31 Javascript
微信小程序 网络API 上传、下载详解
Nov 09 Javascript
vue2.0全局组件之pdf详解
Jun 26 Javascript
webpack构建react多页面应用详解
Sep 15 Javascript
ES6 Map结构的应用实例分析
Jun 26 Javascript
js实现for循环跳过undefined值示例
Jul 02 Javascript
JS实现打砖块游戏
Feb 14 Javascript
浅谈实现在线预览PDF的几种解决办法
Aug 10 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 日志缩略名的创建函数代码
2010/05/26 PHP
php使用fsockopen函数发送post,get请求获取网页内容的方法
2014/11/15 PHP
php通过session防url攻击方法
2014/12/10 PHP
PHP实现生成带背景的图形验证码功能
2016/10/03 PHP
javascript实现轮显新闻标题链接
2007/08/13 Javascript
JavaScript实现网页上的浮动广告的简单方法
2013/06/14 Javascript
jquery select 设置默认选中的示例代码
2014/02/07 Javascript
JavaScript中Function函数与Object对象的关系
2015/12/17 Javascript
AngularJS删除路由中的#符号的方法
2016/09/20 Javascript
vue使用vue-cli快速创建工程
2017/07/28 Javascript
js 开发之autocomplete="off"在chrom中失效的解决办法
2017/09/28 Javascript
浏览器调试动态js脚本的方法(图解)
2018/01/19 Javascript
Bootstrap popover 实现鼠标移入移除显示隐藏功能方法
2018/01/24 Javascript
vue实现的双向数据绑定操作示例
2018/12/04 Javascript
如何使用less实现随机下雪动画详解
2019/01/02 Javascript
详解如何在Vue项目中导出Excel
2019/04/19 Javascript
nodejs制作小爬虫功能示例
2020/02/24 NodeJs
[00:59]DOTA2英雄背景故事——上古巨神
2020/06/28 DOTA
python3读取MySQL-Front的MYSQL密码
2017/05/03 Python
Python3实现简单可学习的手写体识别(实例讲解)
2017/10/21 Python
对python pandas 画移动平均线的方法详解
2018/11/28 Python
在python带权重的列表中随机取值的方法
2019/01/23 Python
在numpy矩阵中令小于0的元素改为0的实例
2019/01/26 Python
python 怎样将dataframe中的字符串日期转化为日期的方法
2019/09/26 Python
python实现ssh及sftp功能(实例代码)
2020/03/16 Python
解决pyPdf和pyPdf2在合并pdf时出现异常的问题
2020/04/03 Python
Python装饰器的应用场景代码总结
2020/04/10 Python
Abe’s of Maine:自1979以来销售相机和电子产品
2016/11/21 全球购物
UNIONBAY官网:美国青少年服装品牌
2019/03/26 全球购物
实习自荐信
2013/10/13 职场文书
自动化专业本科毕业生求职信
2013/10/20 职场文书
青年文明号创建承诺
2014/03/31 职场文书
学生会主席演讲稿
2014/04/25 职场文书
质量整改报告范文
2014/11/08 职场文书
餐厅营销的秘密:为什么老顾客会流水?
2019/08/08 职场文书
python单向链表实例详解
2022/05/25 Python