你是怎么理解ES6中 Decorator 的?使用场景?
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
一、介绍
Decorator,即装饰器,从名字上很容易让我们联想到装饰者模式
简单来讲,装饰者模式就是一种在不改变原类和使用继承的情况下,动态地扩展对象功能的设计理论。
ES6
中Decorator
功能亦如此,其本质也不是什么高大上的结构,就是一个普通的函数,用于扩展类属性和类方法
这里定义一个士兵,这时候他什么装备都没有
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
deprecate
或deprecated
装饰器在控制台显示一条警告,表示该方法将废除
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 的?使用场景?的更多相关文章
- 前端知识体系:JavaScript基础-原型和原型链-理解 es6 中class构造以及继承的底层实现原理
理解 es6 中class构造以及继承的底层实现原理 原文链接:https://blog.csdn.net/qq_34149805/article/details/86105123 1.ES6 cla ...
- 【JS】325- 深度理解ES6中的解构赋值
点击上方"前端自习课"关注,学习起来~ 对象和数组时 Javascript 中最常用的两种数据结构,由于 JSON 数据格式的普及,二者已经成为 Javascript 语言中特别重 ...
- 理解ES6中的Iterator
一.为什么使用Iterator 我们知道,在ES6中新增了很多的特性,包括Map,Set等新的数据结构,算上数组和对象已经有四种数据集合了,就像数组可以使用forEach,对象可以使用for...in ...
- 理解ES6中的Symbol
一.为什么ES6引入Symbol 有时候我们在项目开发的过程中可能会遇到这样的问题,我写了一个对象,而另外的同时则在这个对象里面添加了一个属性或是方法,倘若添加的这个属性或是方法是原本的对象中本来就有 ...
- 深入理解 ES6中的 Reflect
阅读目录 一:Reflect.get(target, name, receiver) 二:Reflect.set(target,name,value,receiver) 三:Reflect.apply ...
- 理解ES6中的Promise
一.Promise的作用 在ajax请求数据的过程中,我们可以异步拿到我们想要的数据,然后在回调中做相应的数据处理. 这样做看上去并没有什么麻烦,但是如果这个时候,我们还需要做另外一个ajax请求,这 ...
- 理解es6 中 arrow function的this
箭头函数相当于定义时候,普通函数.bind(this)箭头函数根本没有自己的this,导致内部的this就是定义时候的外层代码块中的this.外层代码块中的this,则取决于执行时候环境上下文cont ...
- 理解es6中的const与“不变”
const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动. 效果 对于简单类型的数据(数值.字符串.布尔值),值就保存在变量指向的那个内存地址,因此等同于常量. 对于复合类型 ...
- 深入理解es6中的Promise
https://www.jianshu.com/p/9e4af5b77253 https://zhuanlan.zhihu.com/p/30797777 https://segmentfault.co ...
- 深入理解 JavaScript 异步系列(3)—— ES6 中的 Promise
第一部分,Promise 加入 ES6 标准 原文地址 http://www.cnblogs.com/wangfupeng1988/p/6515855.html 未经作者允许不得转载! 从 jquer ...
随机推荐
- Java21 + SpringBoot3使用Spring Security时如何在子线程中获取到认证信息
目录 前言 原因分析 解决方案 方案1:手动设置线程中的认证信息 方案2:使用DelegatingSecurityContextRunnable创建线程 方案3:修改Spring Security安全 ...
- JS Leetcode 525. 连续数组 前缀和加哈希表,小白式讲解让你彻底明白此题
壹 ❀ 引 题目来自LeetCode的525. 连续数组,难度中等,题目描述如下: 给定一个二进制数组 nums , 找到含有相同数量的 0 和 1 的最长连续子数组,并返回该子数组的长度. 示例 1 ...
- 编写高效的代码,你应该了解Array、Memory、ReadOnlySequence
针对"缓冲区"编程是一个非常注重"性能"的地方,我们应该尽可能地避免武断地创建字节数组来存储读取的内容,这样不但会导致大量的字节拷贝,临时创建的字节数组还会带来 ...
- NC14419 线路规划
题目链接 题目 题目描述 Q国的监察院是一个神秘的组织. 这个组织掌握了整个帝国的地下力量,监察着Q国的每一个人. 监察院一共有N个成员,每一个成员都有且仅有1个直接上司,而他只听从其上直接司的命令. ...
- Java容器及其常用方法汇总
1 概述 Java Collections 框架中包含了大量的接口及其实现类和操作它们的算法,主要包括列表(List).集合(Set).映射(Map),如下: 接口 实现类 数据结构 初始容量 加载因 ...
- OpenCV开发笔记(六十六):红胖子8分钟带你总结形态学操作-膨胀、腐蚀、开运算、闭运算、梯度、顶帽、黑帽(图文并茂+浅显易懂+程序源码)
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- defaultdict高级用法
说明 defaultdict数据结构允许调用者提供一个函数,用来在键名缺失的情况下,创建与这个 键对应的值.只要字典发现调用者想要访问的键不存在,就会触发这个函数,以返回应该 与键相关联的默认值 下面 ...
- Jenkins+maven+svn+tomcat持续集成环境
前言 团队最近要把项目发布的工作拿过来,所以需要一个持续集成发布系统 直接上步骤. 下载 http://mirrors.jenkins-ci.org/war/latest/ 直接下载war包,我下载的 ...
- 【Azure Developer】使用 Powershell az account get-access-token 命令获取Access Token (使用用户名+密码)
问题描述 在上篇的文章中,我们使用了JAVA SDK,根据用户名和密码来获取Azure AD的Access Token,这节,我们将使用Powershell az 命令来获取Access Token. ...
- Java this关键字使用 详解+ 证明
1 package com.bytezero.thistest; 2 /** 3 * 4 * @Description 5 * @author Bytezero·zhenglei! Email:420 ...