国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

裝飾器與元數(shù)據(jù)反射(2)屬與類性裝飾器

Shisui / 487人閱讀

摘要:值得注意的是,的返回值復(fù)寫了原始的構(gòu)造函數(shù),原因是類裝飾器必須返回一個(gè)構(gòu)造器函數(shù)。原始構(gòu)造函數(shù)的原型被復(fù)制給的原型,以確保在創(chuàng)建一個(gè)的新實(shí)例時(shí),操作符如愿以償,具體原因可參考鄙人另一篇文章原型與對(duì)象。

上一篇文章中,我們討論了TypeScript源碼中關(guān)于方法裝飾器的實(shí)現(xiàn),搞明白了如下幾個(gè)問(wèn)題:

裝飾器函數(shù)是如何被調(diào)用的?

裝飾器函數(shù)參數(shù)是如何傳入的?

__decorate函數(shù)干了些什么事情?

接下來(lái)我們繼續(xù)屬性裝飾器的觀察。

屬性裝飾器

屬性裝飾器的聲明標(biāo)識(shí)如下:

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

如下我們?yōu)橐粋€(gè)類的屬性添加了一個(gè)名為@logProperty的裝飾器

class Person { 

  @logProperty
  public name: string;
  public surname: string;

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

上一篇解釋過(guò),當(dāng)這段代碼最后被編譯成JavaScript執(zhí)行時(shí),方法__decorate會(huì)被調(diào)用,但此處會(huì)少最后一個(gè)參數(shù)(通過(guò)Object. getOwnPropertyDescriptor屬性描述符)

var Person = (function () {
    function Person(name, surname) {
        this.name = name;
        this.surname = surname;
    }
    __decorate(
      [logProperty],
      Person.prototype,
      "name"
    );
    return Person;
})();

需要注意的是,這次TypeScript編譯器并沒(méi)像方法裝飾器那樣,使用__decorate返回的結(jié)果覆蓋原始屬性。原因是屬性裝飾器并不需要返回什么。

Object.defineProperty(C.prototype, "foo",
    __decorate(
      [log],
      C.prototype,
      "foo",
      Object.getOwnPropertyDescriptor(C.prototype, "foo")
    )
);

那么,接下來(lái)具體實(shí)現(xiàn)這個(gè)@logProperty裝飾器

function logProperty(target: any, key: string) {

  // 屬性值
  var _val = this[key];

  // getter
  var getter = function () {
    console.log(`Get: ${key} => ${_val}`);
    return _val;
  };

  // setter
  var setter = function (newVal) {
    console.log(`Set: ${key} => ${newVal}`);
    _val = newVal;
  };

  // 刪除屬性
  if (delete this[key]) {
    // 創(chuàng)建新的屬性
    Object.defineProperty(target, key, {
      get: getter,
      set: setter,
      enumerable: true,
      configurable: true
    });
  }
}

實(shí)現(xiàn)過(guò)程首先聲明了一個(gè)變量_val,并用所裝飾的屬性值給它賦值(此處的this指向類的原型,key為屬性的名字)。

接著聲明了兩個(gè)方法gettersetter,由于函數(shù)是閉包創(chuàng)建的,所以在其中可以訪問(wèn)變量_val,在其中可以添加額外的自定義行為,這里添加了將屬性值打印在控制臺(tái)的操作。

然后使用delete操作符將原屬性從類的原型中刪除,不過(guò)需要注意的是:如果屬性存在不可配置的屬性時(shí),這里if(delete this[key])會(huì)返回false。而當(dāng)屬性被成功刪除,方法Object.defineProperty()將創(chuàng)建一個(gè)和原屬性同名的屬性,不同的是新的屬性gettersetter方法,使用上面新創(chuàng)建的。

至此,屬性裝飾器的實(shí)現(xiàn)就完成了,運(yùn)行結(jié)果如下:

var me = new Person("Remo", "Jansen");  
// Set: name => Remo

me.name = "Remo H.";                       
// Set: name => Remo H.

name;
// Get: name Remo H.
類裝飾器

類裝飾器的聲明標(biāo)識(shí)如下:

declare type ClassDecorator = (target: TFunction) => TFunction | void;

可以像如下方式使用類裝飾器:

@logClass
class Person { 

  public name: string;
  public surname: string;

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

和之前不同的是,經(jīng)過(guò)TypeScript編譯器編譯為JavaScript后,調(diào)用__decorate函數(shù)時(shí),與方法裝飾器相比少了后兩個(gè)參數(shù)。僅傳遞了Person而非Person.prototype

var Person = (function () {
    function Person(name, surname) {
        this.name = name;
        this.surname = surname;
    }
    Person = __decorate(
      [logClass],
      Person
    );
    return Person;
})();

值得注意的是,__decorate的返回值復(fù)寫了原始的構(gòu)造函數(shù),原因是類裝飾器必須返回一個(gè)構(gòu)造器函數(shù)。接下來(lái)我們就來(lái)實(shí)現(xiàn)上面用到的類裝飾器@logClass

function logClass(target: any) {

  // 保存對(duì)原始構(gòu)造函數(shù)的引用
  var original = target;

  // 用來(lái)生成類實(shí)例的方法
  function construct(constructor, args) {
    var c : any = function () {
      return constructor.apply(this, args);
    }
    c.prototype = constructor.prototype;
    return new c();
  }

  // 新的構(gòu)造函數(shù)
  var f : any = function (...args) {
    console.log("New: " + original.name); 
    return construct(original, args);
  }

  // 復(fù)制原型以便`intanceof`操作符可以使用
  f.prototype = original.prototype;

  // 返回新的構(gòu)造函數(shù)(會(huì)覆蓋原有構(gòu)造函數(shù))
  return f;
}

這里實(shí)現(xiàn)的構(gòu)造器中,聲明了一個(gè)名為original的變量,并將所裝飾類的構(gòu)造函數(shù)賦值給它。接著聲明一個(gè)工具函數(shù)construct,用來(lái)創(chuàng)建類的實(shí)例。然后定義新的構(gòu)造函數(shù)f,在其中調(diào)用原來(lái)的構(gòu)造函數(shù)并將初始化的類名打印在控制臺(tái),當(dāng)然我們也可以添加一些其他自定義的行為。

原始構(gòu)造函數(shù)的原型被復(fù)制給f的原型,以確保在創(chuàng)建一個(gè)Person的新實(shí)例時(shí),instanceof操作符如愿以償,具體原因可參考鄙人另一篇文章原型與對(duì)象。

至此類裝飾器的實(shí)現(xiàn)就完成了,可以驗(yàn)證下:

var me = new Person("Remo", "Jansen");  
// New: Person

me instanceof Person; 
// true

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/101520.html

相關(guān)文章

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

    摘要:可見(jiàn)參數(shù)裝飾器函數(shù)需要個(gè)參數(shù)被裝飾類的原型,裝飾參數(shù)所屬的方法名,參數(shù)的索引。參數(shù)裝飾器不應(yīng)當(dāng)用來(lái)修改構(gòu)造器方法或?qū)傩缘男袨椋粦?yīng)當(dāng)用來(lái)產(chǎn)生某種元數(shù)據(jù)。一旦元數(shù)據(jù)被創(chuàng)建,我們便可以用其它的裝飾器去讀取它。 之前已經(jīng)分別介紹了方法裝飾器、屬性裝飾器和類裝飾器,這篇文章我們來(lái)繼續(xù)關(guān)注這些話題: 參數(shù)裝飾器 裝飾器工廠 我們將圍繞以下這個(gè)例子,來(lái)探討這些概念: class Person...

    Barry_Ng 評(píng)論0 收藏0
  • 裝飾與元數(shù)據(jù)反射(1)方法裝飾

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

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

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

    gaosboy 評(píng)論0 收藏0
  • 聊聊Typescript中的設(shè)計(jì)模式——裝飾篇(decorators)

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

    yiliang 評(píng)論0 收藏0
  • 流暢的 Python - 5. 裝飾閉包

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

    Markxu 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<