首頁  >  文章  >  web前端  >  es6 修飾器是做什麼用

es6 修飾器是做什麼用

青灯夜游
青灯夜游原創
2023-01-30 19:29:501665瀏覽

在es6中,修飾器用來註解或修改類別和類別的方法,依賴ES5的「Object.defineProperty」方法,寫法為「@函數名稱」;修飾者其實就是函數,通常放在類別和類別方法的前面。修飾器可以注入到類別、方法、屬性參數上來擴展類別、屬性、方法、參數的功能。

es6 修飾器是做什麼用

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

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

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

ES6 裝飾器(修飾器)

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

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

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

在上面的程式碼中使用了兩個裝飾器,其中@decorateClass() 裝飾器用在類別本身,用​​於增加或修改類別的功能;@decorateMethods() 裝飾器用在類別的方法,用於註解或修改類別方法。

兩種類型裝飾器(修飾器)

裝飾器只能用於類別和類別的方法,不能用於函數,因為存在函數提升。

裝飾器只能用於類別和類別的方法,下面我們分別看下兩種類型的裝飾器的使用

##類別裝飾器

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

類別裝飾器的參數

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 {}
類別方法裝飾器

類別方法裝飾器用來裝飾類別的方法

類別方法裝飾的參數

    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支援import嗎下一篇:es6支援import嗎