搜尋
首頁web前端前端問答es6中什麼是裝飾器
es6中什麼是裝飾器Mar 23, 2022 pm 01:57 PM
es6裝飾器

在es6中,裝飾器(Decorator)是一種與類別(class)相關的語法,用來註解或修改類別和類別方法;裝飾器其實就是一個編譯時執行的函數,語法“ @函數名”,通常放在類別和類別方法的定義前面。裝飾器有兩種:類別裝飾器和類別方法裝飾器。

es6中什麼是裝飾器

本教學操作環境:windows7系統、ECMAScript 6版、Dell G3電腦。

裝飾器模式(Decorator Pattern)允許為一個現有的物件添加新的功能,同時又不改變其結構。這種類型的設計模式屬於結構型模式,它是作為現有的類別的包裝。

這種模式創建了一個裝飾類,用來包裝原有的類,並在保持類別方法簽名完整性的前提下,提供了額外的功能。

ES6 裝飾器

在 ES6 中,裝飾器(Decorator)是一種與類別相關的語法,用來註解或修改類別和類別方法。

裝飾器其實就是一個函數,通常放在類別和類別方法的前面。

裝飾器對類別的行為的改變,是程式碼編譯時發生的,而不是在執行時;裝飾器的本質就是編譯時執行的函數

裝飾器可以用來裝飾整個類別

@decorateClass
class Example {
    @decorateMethods
    method(){}
}

在上面的代码中使用了两个装饰器,其中 @decorateClass() 装饰器用在类本身,用于增加或修改类的功能;@decorateMethods() 装饰器用在类的方法,用于注释或修改类方法。

两种类型装饰器

装饰器只能用于类和类的方法,不能用于函数,因为存在函数提升。

装饰器只能用于类和类的方法,下面我们分别看下两种类型的装饰器的使用

1、类装饰器

类装饰器用来装饰整个类

类装饰器的参数

target: 类本身,也相当于是 类的构造函数:Class.prototype.constructor。

@decorateClass
class Example {
    //...
}

function decorateClass(target) {
    target.isTestClass = true
}

如上面代码中,装饰器 @decorateClass 修改了 Example 整个类的行为,为 Example 类添加了静态属性 isTestClass。装饰器就是一个函数,decorateClass 函数中的参数 target 就是 Example 类本身,也相当于是类的构造函数 Example.prototype.constructor.

装饰器传参

上面实现的装饰器在使用时是不能传入参数的,如果想要在使用装饰器是传入参数,可以在装饰器外面再封装一层函数

@decorateClass(true)
class Example {
    //...
}

function decorateClass(isTestClass) {
    return function(target) {
  target.isTestClass = isTestClass
  }
}

上面代码中实现的装饰器在使用时可以传递参数,这样就可以根据不同的场景来修改装饰器的行为。

实际开发中,React 与 Redux 库结合使用时,常常需要写成下面这样。

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

有了装饰器,就可以改写上面的代码。

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

2、类方法装饰器

类方法装饰器用来装饰类的方法

类方法装饰器的参数

  • target:

  • 装饰器修饰的类方法是静态方法:target 为类的构造函数

  • 装饰器修饰的类方法是实例方法:target 为类的原型对象

  • method:被修饰的类方法的名称

  • descriptor:被修饰成员的属性描述符

// descriptor对象原来的值如下
{
  value: specifiedFunction,
  enumerable: false,
  configurable: true,
  writable: true
};
class Example {
    @log
    instanceMethod() { }

    @log
    static staticMethod() { }
}

function log(target, methodName, descriptor) {
  const oldValue = descriptor.value;

  descriptor.value = function() {
    console.log(`Calling ${name} with`, arguments);
    return oldValue.apply(this, arguments);
  };

  return descriptor;
}

如上面代码中,装饰器 @log 分别装饰了实例方法 instanceMethod 和 静态方法 staticMethod。@log 装饰器的作用是在执行原始的操作之前,执行 console.log 来输出日志。

类方法装饰器传参

上面实现的装饰器在使用时是不能传入参数的,如果想要在使用装饰器是传入参数,可以在装饰器外面再封装一层函数

class Example {
    @log(1)
    instanceMethod() { }

    @log(2)
    static staticMethod() { }
}

function log(id) {
    return (target, methodName, descriptor) => {
    const oldValue = descriptor.value;

    descriptor.value = function() {
      console.log(`Calling ${name} with`, arguments, `this id is ${id}`);
      return oldValue.apply(this, arguments);
    };

    return descriptor;
  }
}

上面代码中实现的装饰器在使用时可以传递参数,这样就可以根据不同的场景来修改装饰器的行为。

类装饰器与类方法装饰器的执行顺序

如果在一个类中,同时使用装饰器修饰类和类的方法,那么装饰器的执行顺序是:先执行类方法的装饰器,再执行类装饰器。

如果同一个类或同一个类方法有多个装饰器,会像剥洋葱一样,先从外到内进入,然后由内到外执行。

// 类装饰器
function decoratorClass(id){
    console.log('decoratorClass evaluated', id);

    return (target) => {
        // target 类的构造函数
        console.log('target 类的构造函数:',target)
        console.log('decoratorClass executed', id);
    }
}
// 方法装饰器
function decoratorMethods(id){
    console.log('decoratorMethods evaluated', id);
    return (target, property, descriptor) => {
        // target 代表

        // process.nextTick((() => {
            target.abc = 123
            console.log('method target',target)
        // }))
        console.log('decoratorMethods executed', id);

    }
}

@decoratorClass(1)
@decoratorClass(2)
class Example {
    @decoratorMethods(1)
    @decoratorMethods(2)
    method(){}
}

/** 输入日志 **/
// decoratorMethods evaluated 1
// decoratorMethods evaluated 2
// method target Example { abc: 123 }
// decoratorMethods executed 2
// method target Example { abc: 123 }
// decoratorMethods executed 1
// decoratorClass evaluated 1
// decoratorClass evaluated 2
// target 类的构造函数: [Function: Example]
// decoratorClass executed 2
// target 类的构造函数: [Function: Example]
// decoratorClass executed 1

如上面代码中,会先执行类方法的装饰器 @decoratorMethods(1) 和 @decoratorMethods(2),执行完后再执行类装饰器 @decoratorClass(1) 和 @decoratorClass(2)

上面代码中的类方法装饰器中,外层装饰器 @decoratorMethods(1) 先进入,但是内层装饰器 @decoratorMethods(2) 先执行。类装饰器同理。

利用装饰器实现AOP切面编程

function log(target, name, descriptor) {
    var oldValue = descriptor.value;

    descriptor.value = function () {
        console.log(`Calling "${name}" with`, arguments);
        return oldValue.apply(null, arguments);
    }
    return descriptor;
}

// 日志应用
class Maths {
    @log
    add(a, b) {
        return a + b;
    }
}
const math = new Maths();
// passed parameters should get logged now
math.add(2, 4);

【相关推荐:javascript视频教程web前端

以上是es6中什麼是裝飾器的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
es6怎么判断是否为数组es6怎么判断是否为数组Apr 25, 2022 pm 06:43 PM

在es6中,可以利用“Array.isArray()”方法判断对象是否为数组,若判断的对象是数组,返回的结果是true,若判断对象不是数组,返回的结果是false,语法为“Array.isArray(需要检测的js对象)”。

es6中遍历跟迭代的区别是什么es6中遍历跟迭代的区别是什么Apr 26, 2022 pm 02:57 PM

es6中遍历跟迭代的区别是:遍历强调的是要把整个数据依次全部取出来,是访问数据结构的所有元素;而迭代虽然也是依次取出数据,但是并不保证取多少,也不保证把所有的数据取完,是遍历的一种形式。

es6中怎么判断两个对象是否相等es6中怎么判断两个对象是否相等Apr 19, 2022 pm 03:34 PM

在es6中,可用Object对象的is()方法来判断两个对象是否相等,该方法检测两个变量的值是否为同一个值,判断两个对象的引用地址是否一致,语法“Object.is(对象1,对象2)”;该方法会返回布尔值,若返回true则表示两个对象相等。

es6怎么将数字转为字符串es6怎么将数字转为字符串Apr 19, 2022 pm 06:38 PM

转换方法:1、利用“+”给数字拼接一个空字符,语法“数字+""”;2、使用String(),可把对象的值转换为字符串,语法“String(数字对象)”;3、用toString(),可返回数字的字符串表示,语法“数字.toString()”。

es6中assign的用法是什么es6中assign的用法是什么May 05, 2022 pm 02:25 PM

在es6中,assign用于对象的合并,可以将源对象的所有可枚举属性复制到目标对象;若目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性,语法为“Object.assign(...)”

es6怎么改变数组数据es6怎么改变数组数据Apr 26, 2022 am 10:08 AM

改变方法:1、利用splice()方法修改,该方法可以直接修改原数组的内容,语法为“数组.splice(开始位置,修改个数,修改后的值)”;2、利用下标访问数组元素,并重新赋值来修改数组数据,语法为“数组[下标值]=修改后的值;”。

sort排序是es6中的吗sort排序是es6中的吗Apr 25, 2022 pm 03:30 PM

sort排序是es6中的;sort排序是es6中用于对数组的元素进行排序的方法,该方法默认不传参,按照字符编码顺序进行排序,排序顺序可以是字母或数字,并按升序或降序,语法为“array.sort(callback(a,b))”。

import as在es6中的用法是什么import as在es6中的用法是什么Apr 25, 2022 pm 05:19 PM

在es6中,import as用于将若干export导出的内容组合成一个对象返回;ES6的模块化分为导出与导入两个模块,该方法能够将所有的导出内容包裹到指定对象中,语法为“import * as 对象 from ...”。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前By尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
1 個月前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器