这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

一、介绍

Decorator,即装饰器,从名字上很容易让我们联想到装饰者模式

简单来讲,装饰者模式就是一种在不改变原类和使用继承的情况下,动态地扩展对象功能的设计理论。

ES6Decorator功能亦如此,其本质也不是什么高大上的结构,就是一个普通的函数,用于扩展类属性和类方法

这里定义一个士兵,这时候他什么装备都没有

class soldier{
}

定义一个得到 AK 装备的函数,即装饰器

function strong(target){
target.AK = true
}

使用该装饰器对士兵进行增强

@strong
class soldier{
}

这时候士兵就有武器了

soldier.AK // true

上述代码虽然简单,但也能够清晰看到了使用Decorator两大优点:

  • 代码可读性变强了,装饰器命名相当于一个注释
  • 在不改变原有代码情况下,对原来功能进行扩展

二、用法

Docorator修饰对象为下面两种:

  • 类的装饰
  • 类属性的装饰

类的装饰

当对类本身进行装饰的时候,能够接受一个参数,即类本身

将装饰器行为进行分解,大家能够有个更深入的了解

@decorator
class A {} // 等同于 class A {}
A = decorator(A) || A;

下面@testable就是一个装饰器,target就是传入的类,即MyTestableClass,实现了为类添加静态属性

@testable
class MyTestableClass {
// ...
} function testable(target) {
target.isTestable = true;
} MyTestableClass.isTestable // true

如果想要传递参数,可以在装饰器外层再封装一层函数

function testable(isTestable) {
return function(target) {
target.isTestable = isTestable;
}
} @testable(true)
class MyTestableClass {}
MyTestableClass.isTestable // true @testable(false)
class MyClass {}
MyClass.isTestable // false

类属性的装饰

当对类属性进行装饰的时候,能够接受三个参数:

  • 类的原型对象
  • 需要装饰的属性名
  • 装饰属性名的描述对象

首先定义一个readonly装饰器

function readonly(target, name, descriptor){
descriptor.writable = false; // 将可写属性设为false
return descriptor;
}

使用readonly装饰类的name方法

class Person {
@readonly
name() { return `${this.first} ${this.last}` }
}

相当于以下调用

readonly(Person.prototype, 'name', descriptor);

如果一个方法有多个装饰器,就像洋葱一样,先从外到内进入,再由内到外执行

function dec(id){
console.log('evaluated', id);
return (target, property, descriptor) =>console.log('executed', id);
} class Example {
@dec(1)
@dec(2)
method(){}
}
// evaluated 1
// evaluated 2
// executed 2
// executed 1

外层装饰器@dec(1)先进入,但是内层装饰器@dec(2)先执行

注意

装饰器不能用于修饰函数,因为函数存在变量声明情况

var counter = 0;

var add = function () {
counter++;
}; @add
function foo() {
}

编译阶段,变成下面

var counter;
var add; @add
function foo() {
} counter = 0; add = function () {
counter++;
};

意图是执行后counter等于 1,但是实际上结果是counter等于 0

三、使用场景

基于Decorator强大的作用,我们能够完成各种场景的需求,下面简单列举几种:

使用react-redux的时候,如果写成下面这种形式,既不雅观也很麻烦

class MyReactComponent extends React.Component {}

export default connect(mapStateToProps, mapDispatchToProps)(MyReactComponent);

通过装饰器就变得简洁多了

@connect(mapStateToProps, mapDispatchToProps)
export default class MyReactComponent extends React.Component {}

mixins,也可以写成装饰器,让使用更为简洁了

function mixins(...list) {
return function (target) {
Object.assign(target.prototype, ...list);
};
} // 使用
const Foo = {
foo() { console.log('foo') }
}; @mixins(Foo)
class MyClass {} let obj = new MyClass();
obj.foo() // "foo"

下面再讲讲core-decorators.js几个常见的装饰器

@antobind

autobind装饰器使得方法中的this对象,绑定原始对象

import { autobind } from 'core-decorators';

class Person {
@autobind
getPerson() {
return this;
}
} let person = new Person();
let getPerson = person.getPerson; getPerson() === person;
// true

@readonly

readonly装饰器使得属性或方法不可写

import { readonly } from 'core-decorators';

class Meal {
@readonly
entree = 'steak';
} var dinner = new Meal();
dinner.entree = 'salmon';
// Cannot assign to read only property 'entree' of [object Object]

@deprecate

deprecatedeprecated装饰器在控制台显示一条警告,表示该方法将废除

import { deprecate } from 'core-decorators';

class Person {
@deprecate
facepalm() {} @deprecate('功能废除了')
facepalmHard() {}
} let person = new Person(); person.facepalm();
// DEPRECATION Person#facepalm: This function will be removed in future versions. person.facepalmHard();
// DEPRECATION Person#facepalmHard: 功能废除了

参考文献

  • https://es6.ruanyifeng.com/#docs/decorator

你是怎么理解ES6中 Decorator 的?使用场景?的更多相关文章

  1. 前端知识体系:JavaScript基础-原型和原型链-理解 es6 中class构造以及继承的底层实现原理

    理解 es6 中class构造以及继承的底层实现原理 原文链接:https://blog.csdn.net/qq_34149805/article/details/86105123 1.ES6 cla ...

  2. 【JS】325- 深度理解ES6中的解构赋值

    点击上方"前端自习课"关注,学习起来~ 对象和数组时 Javascript 中最常用的两种数据结构,由于 JSON 数据格式的普及,二者已经成为 Javascript 语言中特别重 ...

  3. 理解ES6中的Iterator

    一.为什么使用Iterator 我们知道,在ES6中新增了很多的特性,包括Map,Set等新的数据结构,算上数组和对象已经有四种数据集合了,就像数组可以使用forEach,对象可以使用for...in ...

  4. 理解ES6中的Symbol

    一.为什么ES6引入Symbol 有时候我们在项目开发的过程中可能会遇到这样的问题,我写了一个对象,而另外的同时则在这个对象里面添加了一个属性或是方法,倘若添加的这个属性或是方法是原本的对象中本来就有 ...

  5. 深入理解 ES6中的 Reflect

    阅读目录 一:Reflect.get(target, name, receiver) 二:Reflect.set(target,name,value,receiver) 三:Reflect.apply ...

  6. 理解ES6中的Promise

    一.Promise的作用 在ajax请求数据的过程中,我们可以异步拿到我们想要的数据,然后在回调中做相应的数据处理. 这样做看上去并没有什么麻烦,但是如果这个时候,我们还需要做另外一个ajax请求,这 ...

  7. 理解es6 中 arrow function的this

    箭头函数相当于定义时候,普通函数.bind(this)箭头函数根本没有自己的this,导致内部的this就是定义时候的外层代码块中的this.外层代码块中的this,则取决于执行时候环境上下文cont ...

  8. 理解es6中的const与“不变”

    const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动. 效果 对于简单类型的数据(数值.字符串.布尔值),值就保存在变量指向的那个内存地址,因此等同于常量. 对于复合类型 ...

  9. 深入理解es6中的Promise

    https://www.jianshu.com/p/9e4af5b77253 https://zhuanlan.zhihu.com/p/30797777 https://segmentfault.co ...

  10. 深入理解 JavaScript 异步系列(3)—— ES6 中的 Promise

    第一部分,Promise 加入 ES6 标准 原文地址 http://www.cnblogs.com/wangfupeng1988/p/6515855.html 未经作者允许不得转载! 从 jquer ...

随机推荐

  1. [JVM] CPU缓存一致性协议

    CPU缓存一致性协议 CPU高速缓存 CPU缓存是位于cpu和内存之间的临时数据交换器,它的容量比内存小的夺但是交换速度要比内存快得多,主要是为了解决cpu运行时的处理速度与内存读写速度不匹配的问题. ...

  2. 函数防抖与节流 - js

    防抖(debounce)和节流(throttle)是在 高频次调用函数 的场景下,常用的解决方案了.故名思意,可以节省开销,优化体验. 二者的区别: 防抖: 我们让想要执行的函数只在最后一次调用完一小 ...

  3. 了解一下基本的tcp代理配置

    我们首先用一个简单例子了解一下基本的tcp代理配置 worker_processes 1; #nginx worker 数量 error_log logs/error.log; #指定错误日志文件路径 ...

  4. Kubernetes 1.26.0实战:在本地配置k8s集群

    阶段一:开发环境及版本 以下环境均来自官网: 本地宿主机环境:Windows 10 21H2 64位 虚拟机软件:VMware workstation 15.5 pro 虚拟机镜像版本:ubuntu- ...

  5. Python 字典与集合

    字典(Dictionary) 字典介绍 字典是"键值对"的无序可变序列,字典中的每个元素都是一个"键值对",包含:"键对象"和"值 ...

  6. win32 - 匿名管道的使用

    目标: 创建一个父进程和子进程,在子进程的控制台窗口输入数据,数据通过管道发送给父进程,父进程的控制台窗口读取数据,最后将数据打印出来. Parent.cpp //CMD.exe #include & ...

  7. 文心一言 VS 讯飞星火 VS chatgpt (201)-- 算法导论15.2 6题

    六.用go语言,证明:对 n 个元素的表达式进行完全括号化,恰好需要 n-1 对括号. 文心一言,代码正常运行: 在Go语言中,证明对n个元素的表达式进行完全括号化恰好需要n-1对括号,可以通过数学归 ...

  8. PrettyTable模块

    # 用来生成美观的ASCII格式的表格 pip install prettytable # 导入 from prettytable import PrettyTable # 使用 tb = pt.Pr ...

  9. 【Azure Cache for Redis】Redis的导出页面无法配置Storage SAS时通过az cli来完成

    问题描述 在Azure Redis的导出页面,突然不能配置Storage Account的SAS作为授权方式. 那么是否可以通过AZ CLI或者是Powershell来实现SAS的配置呢? 问题解答 ...

  10. 【Azure 应用服务】FTP 部署 Vue 生成的静态文件至 Linux App Service 后,访问App Service URL依旧显示Azure默认页面问题

    问题描述 将 JS项目打包为静态文件后,通过 FTP 上传到 App Service For Linux 的 /home/site/wwwroot文件夹中.但打开App Service URL 后依旧 ...