为什么枚举会转化为函数?

时间:2017-11-18 08:13:47

标签: javascript typescript

考虑:

enum Colors {
    Red,
    Green,
    Blue
}

它转化为:

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";
// ...
     

并跳过关闭,但也许我仍然遗漏了一些东西。

所以问题仍然存在:为什么要将它包装在一个立即执行的函数中?

2 个答案:

答案 0 :(得分: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";

尺寸差异很大。

答案 1 :(得分: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的现有定义(读取对象)。

如果我们从第二个= 3定义中省略enum Colors部分,TypeScript也会正确显示报告以下错误。

  

在具有多个声明的枚举中,只有一个声明可以省略其第一个枚举元素的初始值设定项。

     

(枚举成员)Colors.Black = 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 = {}));
    

    这可能看起来不是一个如此有利可图的命题,但要考虑变量名称何时更长。

  3. 有关该主题的更多信息"为何选择IIFE":http://gregfranko.com/blog/i-love-my-iife/

    希望这有帮助。