博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ECMAScript Decorators---装饰器
阅读量:5963 次
发布时间:2019-06-19

本文共 3921 字,大约阅读时间需要 13 分钟。

ECMAScript Decorators---装饰器

Decorators是什么

  • Decorators可以改变类方法和类实例字段的属性和行为,使我们可以灵活地使用更简单的语法动态实现这些内容,是非侵入式的。---举例,你给手机添加一个外壳罢了,并不影响手机原有的通话、充电等功能

应用场景

  • Decorators的经典的应用是AOP编程,比如“日志系统”,日志系统的作用是记录系统的行为操作,它在不影响原有系统的功能的基础上增加记录环节
  • 更加抽象的理解,可以理解为给数据流做一层filter,因此 AOP 的典型应用包括安全检查、缓存、调试、持久化等等。

原理

  • Decorators的本质是利用了ES5的Object.defineProperty属性,这三个参数其实是和Object.defineProperty参数一致的,因此不能更改
  • object 必需。要在其上添加或修改属性的对象 这可能是一个本机JavaScript对象(即用户定义的对象或内置对象)或 DOM 对象。
  • propertyname必需。一个包含属性名称的字符串
  • descriptor 必需。 属性描述符。它可以针对数据属性或访问器属性。
  • 举例说明
var myObj = {    myPropOne: 1,    myPropTwo: 2};// modify property descriptorObject.defineProperty( myObj, 'myPropOne', {    writable: false, // 是否允许该属性值更改    enumerable: false, // 是否允许key被枚举,话句话说for in 或者Object.keys() 不会输出key    configurable: false// 目标属性是否可以被删除或是否可以再次修改特性} );复制代码

应用举例

  1. 类方法 @readonly
class User {    constructor( firstname, lastName ) {        this.firstname = firstname;        this.lastName = lastName;    }        @readonly    getFullName() {        return this.firstname + ' ' + this.lastName;    }}// create instancelet user = new User( 'John', 'Doe' );console.log( user.getFullName() );// 某天我不小心重写了这个方法User.prototype.getFullName = function() {    return 'HACKED!';}// 输出 HACKED! 与预期不符,怎么避免此类情况发生// 方法1 这是最好的解决方案么?修饰器登场Object.defineProperty( User.prototype, 'getFullName', {    writable: false});// 将此方法添加到修饰方法getFullName上function readonly( target, property, descriptor ) {    descriptor.writable = false;    return descriptor;}复制代码
  1. 类方法 @log日志打印
function log( logMessage ) {    // return decorator function    return function ( target, property, descriptor ) {        // save original value, which is method (function)        let originalMethod = descriptor.value;        // replace method implementation        descriptor.value = function( ...args ) {            console.log( '[LOG]', logMessage );            // here, call original method            // `this` points to the instance            return originalMethod.call( this, ...args );        };        return descriptor;    }}class User {    constructor( firstname, lastName ) {        this.firstname = firstname;        this.lastName = lastName;    }    @log('calling getFullName method on User class')    getFullName() {        return this.firstname + ' ' + this.lastName;    }}var user = new User( 'John', 'Doe' );console.log( user.getFullName() );复制代码
  1. 类的属性 大小写转换
// 解释:descriptor.initializer函数由Babel内部使用来创建对象属性的属性描述符的值function toCase( CASE = 'lower' ) {    return function ( target, name, descriptor ) {        let initValue = descriptor.initializer();            descriptor.initializer = function(){            return ( CASE == 'lower' ) ?             initValue.toLowerCase() : initValue.toUpperCase();        }            return descriptor;    }}class User {    @toCase( 'upper' )    firstName = 'default_first_name';    lastName = 'default_last_name';    constructor( firstName, lastName ) {        if( firstName ) this.firstName = firstName;        if( lastName ) this.lastName = lastName;    }    getFullName() {        return this.firstName + ' ' + this.lastName;    }}console.log( new User() );复制代码
  1. 类装饰器
function withLoginStatus( UserRef ) {  return class extends UserRef {      constructor( ...args ) {          super( ...args );          this.isLoggedIn = false;      }      setLoggedIn() {          this.isLoggedIn = true;      }  }}@withLoginStatusclass User {  constructor( firstName, lastName ) {      this.firstName = firstName;      this.lastName = lastName;  }}let user = new User( 'John', 'Doe' );console.log( 'Before ===> ', user );// set logged inuser.setLoggedIn();console.log( 'After ===> ', user );复制代码

babel 装换

  • 构建babel装换
1、创建项目文件2、命令行进入该项目目录 npm init 3、npm install babel-core babel-plugin-transform-decorators4、安装 npm install babel-plugin-transform-decorators-legacy --save-dev5、.babelrc添加{    "plugins": [        "transform-decorators-legacy"  ]}复制代码

参考链接

原文发布时间为:2018年06月28日

原文作者:chen小白

本文来源:
如需转载请联系原作者
你可能感兴趣的文章
26.Extjs 部门列表信息展示页面
查看>>
maven学习手记 - 3
查看>>
Window 命令行神器:cmder
查看>>
Oracle 索引
查看>>
23. requests安装与使用
查看>>
讲讲不怎么有用却很有意义的包围体测试
查看>>
Redhat/Centos6.x安装Chrome
查看>>
JSP 9大内置对象详解
查看>>
MYSQL 随笔
查看>>
LNMP环境下打击那搭建Bugfree
查看>>
mybatis初接触
查看>>
Java一次性读取文件的内容
查看>>
TestMap
查看>>
《测之重器——自动化测试框架搭建指南》
查看>>
Kent Beck揭秘Facebook开发部署流程
查看>>
AsDataView Dataview ,DataTable 跟linq的相互转化
查看>>
ABP(现代ASP.NET样板开发框架)系列之16、ABP应用层——数据传输对象(DTOs)
查看>>
在html页头设置不缓存
查看>>
这就是爱情
查看>>
域名服务交易平台收集
查看>>