簡體   English   中英

Typescript / Javascript自定義屬性裝飾器

[英]Typescript / Javascript custom Property decorators

我剛剛開始更深入地學習Typescript和ES6功能,並且對如何創建自定義的Property Decorator以及它如何實際工作有一些誤解。

這是我關注的資源Source1 Source2

這是我的自定義除草劑。

export const Required = (target: Object, key: string) => {

    let value: any = target[key];

    const getter = () => {
        if (value !== undefined) return value;

        throw new RequiredPropertyError(MetadataModule.GetClassName(target), key, ErrorOptions.RequiredProperty)
    }

    const setter = (val) => value = val;

    if (delete this[key]) {
        Object.defineProperty(target, key, {
            get: getter,
            set: setter,
            enumerable: true,
            configurable: true,
        });
    }
}

像這樣應用

export classMyClass{
    @Required
    public Items: number[];
}

我不明白的是為什么它的工作原理與您期望的不同。 很好,但是我不知道它是否適合我們稱之為“裝飾者理念”的作品,

讓我解釋一下我不明白的

從第一行代碼開始。

 let value: any = target[key]; 

我希望該value將使用Items值初始化,但undefined ,為什么? 怎么樣? 我真的不明白。

我一直關注這兩個資源,發現令我感到困惑的第一件事是,一個人使用target[key]來初始化value而另一個人使用了this[key]this實際上不應該引用Required。

我也感到困惑的是這部分

 if (delete this[key]) {
        Object.defineProperty(target, key, {
            get: getter,
            set: setter,
            enumerable: true,
            configurable: true,
        });
    }

首先,為什么我需要刪除this [key]? 根據我的理解,在本例中為Required ,它應指代當前對象的上下文,而在調試時則是如此。

其次,在我的案例MyClass ,該Object.defineProperty將在目標類上創建一個具有鍵名的屬性,但是此屬性不存在嗎?

前進並使用設置器設置value ,設置器參數val如何知道應保存哪些數據? 我的意思是它要去哪里?

謝謝大家

那里有很多問題,但是我會盡力回答所有問題:)

我希望該value將使用Items值初始化,但undefined ,為什么?

當實例化MyClass類並運行裝飾器代碼時,該對象的所有屬性的值都undefined (即使您使用的不是TypeScript屬性初始化器)。

this不應該指Required嗎?

是的,我認為您的示例中確實如此。 但是在Source1鏈接中 ,裝飾器是使用函數表達式( function logProperty() )定義的; 在您的示例中,您已將其切換為箭頭函數表達式( const Required = ( ... ) => )。 此開關可能會更改this所指的內容。 為了安全起見,請將其切換為target[key]

為什么我需要刪除此[鍵]?

此代碼塊將刪除原始的Items屬性,並將其替換為具有相同名稱的屬性,該屬性使您可以監視變量的獲取和設置。 delete this[key]行可防止該屬性不可配置。 如果有問題的屬性是不可配置的,則delete運算符將返回false 。)

在我的案例MyClass ,Object.defineProperty將在目標類上創建一個具有鍵名的屬性,但是此屬性不存在嗎?

是的,如上所述,此代碼將屬性替換為新屬性。 設置了新屬性,使您可以觀察此變量的獲取和設置。

前進並使用設置器設置value ,設置器參數val如何知道應保存哪些數據? 我的意思是它要去哪里?

當你的新Items屬性設置,該setter函數被調用的財產即將被新的值作為參數(這個setter功能以前設置為使用setter函數Object.defineProperty )。 setter函數的實現將設置value ,該value是對target[key]的引用。 結果, Items的值被更新。


為了更好地理解所有這些是如何工作的,請嘗試添加一些日志記錄語句,然后嘗試獲取/設置Items屬性:

export const Required = (target: Object, key: string) => {
    let value: any = target[key];

    console.log('Initialize the Required decorator; value:', value);

    const getter = () => {
        console.log('Inside the getter; value is:', value);
        if (value !== undefined) return value;

        throw new RequiredPropertyError(MetadataModule.GetClassName(target), key, ErrorOptions.RequiredProperty);
    };

    const setter = val => {
        console.log('Inside the setter; val is: ', val, 'value is:', value);
        return (value = val);
    };

    if (delete this[key]) {
        console.log('Replacing the "' + key + '" property with a new, configured version');
        Object.defineProperty(target, key, {
            get: getter,
            set: setter,
            enumerable: true,
            configurable: true
        });
    }
};

export class MyClass {
    @Required 
    public Items: number[];
}

// instantiated your class
var mc = new MyClass();

// set the Items property
mc.Items = [4, 5, 6];

// get the value with no Errors
mc.Items;

// set the Items property to undefined
mc.Items = undefined;

// get the value - an Error is thrown
mc.Items;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM