2017-11-18 160 views
17

考慮:爲什麼枚舉轉換成函數?

enum Colors { 
    Red, 
    Green, 
    Blue 
} 

它transpiles到這一點:

這個結果
var Colors; 
(function (Colors) { 
    Colors[Colors["Red"] = 0] = "Red"; 
    Colors[Colors["Green"] = 1] = "Green"; 
    Colors[Colors["Blue"] = 2] = "Blue"; 
})(Colors || (Colors = {})); 

大多數問題在Enums in TypeScript: what is the JavaScript code doing?作了解答。

我引用的答案:

這是一個 '立即執行功能'

進一步壓低話題:

認爲他們很可能只是走:

var Colors; 
Colors || (Colors = {}); 
Colors[Colors["Cyan"] = 3] = "Cyan"; 
// ... 

並跳過關閉,但也許我仍然失去了一些東西。

所以問題仍然存在:爲什麼將這個包裝在一個立即執行的函數中?

+3

這裏有一個非常詳細的解釋:https://basarat.gitbooks.io/typescript/content/docs/enums.html – DSCH

+0

@DSCH你的鏈接沒有解決爲什麼需要關閉的問題。 –

+0

最可能的解釋是,這只是個人偏好的問題,無論誰寫這部分譯員。 – JJJ

回答

11

我相信TypeScript使用IIFE(又名立即調用函數表達式),因爲變量名可以被縮小。如果您有很長的枚舉名稱,例如MySuperAmazingStatesNeededForWhateverIWantEnum,它可以在IIFE內部精縮到只有一個字母

// amazing_enum.js 
var MySuperAmazingStatesNeededForWhateverIWantEnum; 
(function MySuperAmazingStatesNeededForWhateverIWantEnum() { 
    MySuperAmazingStatesNeededForWhateverIWantEnum[MySuperAmazingStatesNeededForWhateverIWantEnum["Red"] = 0] = "Red"; 
    MySuperAmazingStatesNeededForWhateverIWantEnum[MySuperAmazingStatesNeededForWhateverIWantEnum["Green"] = 1] = "Green"; 
    MySuperAmazingStatesNeededForWhateverIWantEnum[MySuperAmazingStatesNeededForWhateverIWantEnum["Blue"] = 2] = "Blue"; 
})(MySuperAmazingStatesNeededForWhateverIWantEnum || (MySuperAmazingStatesNeededForWhateverIWantEnum = {})); 

// amazing_enum.min.js 
var MySuperAmazingStatesNeededForWhateverIWantEnum;!function e(){e[e.t=0]="Red",e[e.u=1]="Green",e[e.m=2]="Blue"}(MySuperAmazingStatesNeededForWhateverIWantEnum||(MySuperAmazingStatesNeededForWhateverIWantEnum={})); 

沒有IIFE縮小不會被視爲有效

// amazing_enum.js 
var MySuperAmazingStatesNeededForWhateverIWantEnum; 
MySuperAmazingStatesNeededForWhateverIWantEnum || (MySuperAmazingStatesNeededForWhateverIWantEnum = {}), 
MySuperAmazingStatesNeededForWhateverIWantEnum[MySuperAmazingStatesNeededForWhateverIWantEnum.Red = 0] = "Red"; 
MySuperAmazingStatesNeededForWhateverIWantEnum[MySuperAmazingStatesNeededForWhateverIWantEnum.Green = 1] = "Green"; 
MySuperAmazingStatesNeededForWhateverIWantEnum[MySuperAmazingStatesNeededForWhateverIWantEnum.Blue = 2] = "Blue"; 

// amazing_enum.min.js 
var MySuperAmazingStatesNeededForWhateverIWantEnum;MySuperAmazingStatesNeededForWhateverIWantEnum||(MySuperAmazingStatesNeededForWhateverIWantEnum={}),MySuperAmazingStatesNeededForWhateverIWantEnum[MySuperAmazingStatesNeededForWhateverIWantEnum.t=0]="Red",MySuperAmazingStatesNeededForWhateverIWantEnum[MySuperAmazingStatesNeededForWhateverIWantEnum.u=1]="Green",MySuperAmazingStatesNeededForWhateverIWantEnum[MySuperAmazingStatesNeededForWhateverIWantEnum.m=2]="Blue"; 

在尺寸上的差異是巨大的。

+0

好的縮小器會重命名「MySuperAmazingStatesNeededForWhateverIWantEnum」的所有實例,而不僅僅是IIFE中的那些實例。 – str

+0

@str這將取決於變量是否需要從外部訪問 – LegionMammal978

+0

@ LegionMammal978這並不重要,因爲「所有實例」將被重命名,即使是外部的。 – str

0

這是因爲在TypeScript中,枚舉是開放式的。

這意味着,你可以這樣做如下:

enum Colors { 
Red, 
Green, 
Blue 
} 

console.log(Colors); // { '0': 'Red', '1': 'Green', '2': 'Blue', Red: 0, Green: 1, Blue: 2 } 

enum Colors { 
Black = 3, 
White 
} 

console.log(Colors); // { '0': 'Red', '1': 'Green', '2': 'Blue', '3': 'Black', '4': 'White', Red: 0, Green: 1, Blue: 2, Black: 3, White: 4 } 

這意味着,你可以添加新的成員已定義enum。把它看作C#中的部分類或打字稿中的interface

IIFE的使用使得可以拾取同名的enum的任何現有定義(讀取對象)。

如果我們省略第二個enum Colors定義中的= 3部分,TypeScript正確顯示報告以下錯誤。

在一個有多個聲明的枚舉中,只有一個聲明可以爲其第一個枚舉元素省略初始值設定項。

(枚舉成員)顏色。黑色= 0

在這裏閱讀更多:https://basarat.gitbooks.io/typescript/docs/enums.html

編輯:還要注意是否有使用IIFE的一些好處。

  1. 本地範圍優化:將變量聲明爲儘可能接近您首次使用該變量總是有益的。 JavaScript可以從本地範圍遍歷到全局範圍,以查找變量。因此,使用局部變量可以提供性能優勢。
  2. 縮小率:這已在@Piotr Kocia的回答中提及。這意味着您也可以爲IIFE使用較短的變量名稱。

    var Colors; 
    (function (C) { 
        C[C["Red"] = 0] = "Red"; 
        C[C["Green"] = 1] = "Green"; 
        C[C["Blue"] = 2] = "Blue"; 
    })(Colors || (Colors = {})); 
    

    在這一點上,這可能看起來不那麼有利可圖,但考慮一下變量名稱是否更長。

更多的題目是 「爲什麼IIFE」:http://gregfranko.com/blog/i-love-my-iife/

希望這有助於。

+2

沒有IIFE的枚舉仍然是開放式的 – Whatever

+0

@PiotrKocia謝謝你指出。請檢查更新後的答案:) –