[英]Typescript / Javascript custom Property decorators
我剛剛開始更深入地學習Typescript和ES6功能,並且對如何創建自定義的Property Decorator以及它如何實際工作有一些誤解。
這是我的自定義除草劑。
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.