成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

裝飾器與元數(shù)據(jù)反射(3)參數(shù)裝飾器

Barry_Ng / 3413人閱讀

摘要:可見參數(shù)裝飾器函數(shù)需要個參數(shù)被裝飾類的原型,裝飾參數(shù)所屬的方法名,參數(shù)的索引。參數(shù)裝飾器不應(yīng)當(dāng)用來修改構(gòu)造器方法或?qū)傩缘男袨椋粦?yīng)當(dāng)用來產(chǎn)生某種元數(shù)據(jù)。一旦元數(shù)據(jù)被創(chuàng)建,我們便可以用其它的裝飾器去讀取它。

之前已經(jīng)分別介紹了方法裝飾器、屬性裝飾器和類裝飾器,這篇文章我們來繼續(xù)關(guān)注這些話題:

參數(shù)裝飾器

裝飾器工廠

我們將圍繞以下這個例子,來探討這些概念:

class Person { 

  public name: string;
  public surname: string;

  constructor(name : string, surname : string) { 
    this.name = name;
    this.surname = surname;
  }

  public saySomething(something : string) : string { 
    return this.name + " " + this.surname + " says: " + something; 
  }
}
參數(shù)裝飾器

TypeScript對于參數(shù)裝飾器的聲明如下

declare type ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;

如下我們?yōu)轭?b>Person的saySomething方法的參數(shù)添加一個參數(shù)裝飾器

public saySomething(@logParameter something : string) : string { 
    return this.name + " " + this.surname + " says: " + something; 
}

最終被編譯為JavaScript的樣子為:

Object.defineProperty(Person.prototype, "saySomething",
    __decorate(
        [__param(0, logParameter)],
        Person.prototype,
        "saySomething",
        Object.getOwnPropertyDescriptor(Person.prototype, "saySomething")
    )
);
return Person;

如果將其和之前的裝飾器比較,是否會發(fā)現(xiàn)又使用了Object.defineProperty()方法,那么是否意味著saySomething將被__decorated函數(shù)的返回值替換?

我們發(fā)現(xiàn)這里有個新函數(shù)__param,TypeScript編譯器生成如下:

var __param = this.__param || function (index, decorator) {
    // 返回一個裝飾器函數(shù)
    return function (target, key) {
        // 應(yīng)用裝飾器(忽略返回值)
        decorator(target, key, index); 
    }
};

如上所示,調(diào)用參數(shù)裝飾器,其并沒有返回值,這就意味著,函數(shù)__decorate的調(diào)用返回并沒有覆蓋方法saySomething,也很好理解:參數(shù)裝飾器要毛返回。

可見參數(shù)裝飾器函數(shù)需要3個參數(shù):被裝飾類的原型,裝飾參數(shù)所屬的方法名,參數(shù)的索引。具體的實現(xiàn)如下:

function logParameter(target: any, key : string, index : number) {
  var metadataKey = `log_${key}_parameters`;
  if (Array.isArray(target[metadataKey])) {
    target[metadataKey].push(index);
  }
  else { 
    target[metadataKey] = [index];
  }
}

其中向類的原型中增加一個新的屬性metadataKey,該屬性值是一個數(shù)組,包含所裝飾參數(shù)的索引,可以把它當(dāng)作元數(shù)據(jù)。

參數(shù)裝飾器不應(yīng)當(dāng)用來修改構(gòu)造器、方法或?qū)傩缘男袨?,它只?yīng)當(dāng)用來產(chǎn)生某種元數(shù)據(jù)。一旦元數(shù)據(jù)被創(chuàng)建,我們便可以用其它的裝飾器去讀取它。

裝飾器工廠

官方TypeScript裝飾器建議定義一個如下的裝飾器工廠:

裝飾器工廠首先是一個函數(shù),它接受任意數(shù)量的參數(shù),同時返回如前所述的四種之一特定類型的裝飾器。

雖然已經(jīng)討論四種裝飾是如何實現(xiàn)及使用的,但還是有一些可以改進的地方,觀察下面的代碼片段:

@logClass
class Person { 

  @logProperty
  public name: string;

  public surname: string;

  constructor(name : string, surname : string) { 
    this.name = name;
    this.surname = surname;
  }

  @logMethod
  public saySomething(@logParameter something : string) : string { 
    return this.name + " " + this.surname + " says: " + something; 
  }
}

這里裝飾器的使用是沒問題的,但如果我們可以不關(guān)心裝飾器的類型,而在任何地方使用豈不方便,就像下面的樣子:

@log
class Person { 

  @log
  public name: string;

  public surname: string;

  constructor(name : string, surname : string) { 
    this.name = name;
    this.surname = surname;
  }

  @log
  public saySomething(@log something : string) : string { 
    return this.name + " " + this.surname + " says: " + something; 
  }
}

這邊是裝飾器工廠的使用訴求,它可以識別具體情況下該使用哪種類型的裝飾器,幸運的是,我們可以通過傳遞給裝飾器的參數(shù)來區(qū)分它的類型。

function log(...args : any[]) {
  switch(args.length) {
    case 1:
      return logClass.apply(this, args);
    case 2:
      return logProperty.apply(this, args);
    case 3:
      if(typeof args[2] === "number") {
        return logParameter.apply(this, args);
      }
      return logMethod.apply(this, args);
    default:
      throw new Error("Decorators are not valid here!");
  }
}

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/101516.html

相關(guān)文章

  • 裝飾與元數(shù)據(jù)反射(1)方法裝飾

    摘要:使用裝飾器的方法很簡單在裝飾器名前加字符,寫在想要裝飾的方法上,類似寫注釋的方式裝飾器實際上是一個函數(shù),入?yún)樗b飾的方法,返回值為裝飾后的方法。經(jīng)過裝飾過的方法,它依然按照原來的方式執(zhí)行,只是額外執(zhí)行了附件的裝飾器函數(shù)的功能。 讓我來深入地了解一下TypeScript對于裝飾器模式的實現(xiàn),以及反射與依賴注入等相關(guān)特性。 在Typescript的源代碼中,可以看到裝飾器能用來修飾cla...

    xiaochao 評論0 收藏0
  • 裝飾與元數(shù)據(jù)反射(4)元數(shù)據(jù)反射

    摘要:慶幸的是,已經(jīng)支持反射機制,來看看這個特性吧元數(shù)據(jù)反射可以通過安裝包來使用元數(shù)據(jù)反射的若要使用它,我們需要在中設(shè)置為,同時添加的引用,同時加載文件。復(fù)雜類型序列化的團隊為復(fù)雜類型的元數(shù)據(jù)序列化做出了努力。 本篇內(nèi)容包括如下部分: 為什么JavaScript中需要反射 元數(shù)據(jù)反射API 基本類型序列化 復(fù)雜類型序列化 為什么JavaScript中需要反射? 關(guān)于反射的概念,摘自百度百...

    gaosboy 評論0 收藏0
  • 裝飾與元數(shù)據(jù)反射(2)屬與類性裝飾

    摘要:值得注意的是,的返回值復(fù)寫了原始的構(gòu)造函數(shù),原因是類裝飾器必須返回一個構(gòu)造器函數(shù)。原始構(gòu)造函數(shù)的原型被復(fù)制給的原型,以確保在創(chuàng)建一個的新實例時,操作符如愿以償,具體原因可參考鄙人另一篇文章原型與對象。 上一篇文章中,我們討論了TypeScript源碼中關(guān)于方法裝飾器的實現(xiàn),搞明白了如下幾個問題: 裝飾器函數(shù)是如何被調(diào)用的? 裝飾器函數(shù)參數(shù)是如何傳入的? __decorate函數(shù)干了...

    Shisui 評論0 收藏0
  • 流暢的 Python - 5. 裝飾閉包

    摘要:看了這一章,發(fā)現(xiàn)原來是裝飾器,又一新知識。期間,裝飾器會做一些額外的工作。書中介紹了模塊中的三個裝飾器。另一個是,這個裝飾器把函數(shù)結(jié)果保存了起來,避免傳入相同參數(shù)時重復(fù)計算。疊放不奇怪,裝飾器返回的就是函數(shù)或可調(diào)用對象。 在 Web 框架 Flask 中,最常看到的或許是以@app.route開頭的那行代碼。由于還是剛接觸 Flask,所以對這種語法還不熟悉??戳诉@一章,發(fā)現(xiàn)原來是裝飾...

    Markxu 評論0 收藏0
  • 聊聊Typescript中的設(shè)計模式——裝飾篇(decorators)

    摘要:本文從裝飾模式出發(fā),聊聊中的裝飾器和注解。該函數(shù)的函數(shù)名。不提供元數(shù)據(jù)的支持。中的元數(shù)據(jù)操作可以通過包來實現(xiàn)對于元數(shù)據(jù)的操作。 ??隨著Typescript的普及,在KOA2和nestjs等nodejs框架中經(jīng)??吹筋愃朴趈ava spring中注解的寫法。本文從裝飾模式出發(fā),聊聊Typescipt中的裝飾器和注解。 什么是裝飾者模式 Typescript中的裝飾器 Typescr...

    yiliang 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<