Подтвердить что ты не робот

Почему перечисление переводится в функцию?

Рассмотрим:

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 = {}));

В большинстве вопросов об этом ответе в перечислены в TypeScript: что делает код JavaScript?.

Я цитирую ответы:

Это "немедленно выполняющая функция"

И далее по теме:

Думаю, они могли бы просто пойти:

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

и пропустите закрытие, но, возможно, Im все еще что-то пропустил.

Итак, остается вопрос: зачем обертывать это в немедленно выполняющейся функции?

4b9b3361

Ответ 1

Я полагаю, что 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={}));

Без МИФИ минификация не будет столь эффективной

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

Разница в размере огромна.

Ответ 2

Это потому, что в 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. Рассмотрим это как частичный класс в С# или interface в typescript.

IIFE используется для того, чтобы любое существующее определение (прочитанный объект) enum с тем же именем можно было поднять.

Также TypeScript корректно отображает отчеты об ошибке ниже, если мы опустим часть = 3 из второго определения enum Colors.

В перечислении с несколькими объявлениями только одно объявление может опустить инициализатор для своего первого элемента перечисления.

(член перечисления) Colors.Black = 0

Подробнее здесь: https://basarat.gitbooks.io/typescript/docs/enums.html

РЕДАКТИРОВАТЬ: Также обратите внимание, что есть некоторые преимущества использования IIFE.

  • Локальная оптимизация области: всегда полезно объявить вашу переменную как можно ближе к первому использованию этой переменной. JavaScript может перемещаться из локальной области в глобальную область, чтобы искать переменную. Таким образом, использование локальной переменной может обеспечить производительность.
  • Minification: об этом уже упоминалось в ответе @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/

Надеюсь, что это поможет.