Вот класс TypeScript:
class Greeter {
public static what(): string {
return "Greater";
}
public subject: string;
constructor(subject: string) {
this.subject = subject;
}
public greet(): string {
return "Hello, " + this.subject;
}
}
Он передается в IIFE, когда TS нацелен на ES5:
var Greeter = /** @class */ (function () {
function Greeter(subject) {
this.subject = subject;
}
Greeter.what = function () {
return "Greater";
};
Greeter.prototype.greet = function () {
return "Hello, " + this.subject;
};
return Greeter;
}());
Однако обычно он работает точно так же, когда он представлен в виде функции-конструктора. Что, конечно, больше похоже на JavaScript и рукописное :)
function Greeter(subject) {
this.subject = subject;
}
Greeter.what = function () {
return "Greater";
};
Greeter.prototype.greet = function () {
return "Hello, " + this.subject;
};
Применение:
Оба блока кода работают одинаково:
Greater.what(); // -> "Greater"
var greater = new Greater("World!");
greater.greet(); // -> "Hello, World!
Какова польза или мотивы для упаковки в IIFE?
Я сделал наивный тест:
console.time("Greeter");
for(let i = 0; i < 100000000; i++) {
new Greeter("world" + i);
}
console.timeEnd("Greeter");
Он показал практически такую же скорость создания экземпляров. Конечно, мы не можем ожидать никакой разницы, потому что IIFE разрешается только один раз.
Я думал, что, может быть, это из-за закрытия, но IIFE не принимает аргументов. Это не должно быть замыканием.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Это сделано для сохранения собственного поведения класса в крайних случаях, подобных этому, когда кто-то пытается использовать класс Greeter до того, как он определен:
// this is javascript code, not TypeScript
console.info(Greeter.What());
class Greeter {
}
Greeter.What = function What() {
return "Greater";
}
С реализацией нативного класса это должно печатать ReferenceError: Greeter is not defined.
При транспиляции и заворачивании в IIFE результат достаточно близок: TypeError: Cannot read property 'What' of undefined.
Без IIFE развернутая функция — это поднятый, а имя Greeter находится в области видимости до того, как оно определено, поэтому возникает другая ошибка: TypeError: Greeter.What is not a function
Обратите внимание, что IIFE не используется для сокрытия частных свойств экземпляра или класса, поскольку в этом нет необходимости. При переносе свойства экземпляра назначаются как свойства для this внутри конструктора, а статические свойства назначаются как свойства объекта Greeter — переменные не создаются.
var не будет поднят
Да, другой ответ правильный - вы должны иметь возможность ввести имя для ссылки на базовый класс, потому что, например, базовый класс может быть миксин. IIFE — это единственный способ безопасно ввести имя, которое не будет конфликтовать ни с чем во внешней области видимости.
Я думаю, что оба ответа верны в отношении разных вещей. Да, var не поднят, но function Greeter сам по себе (как показал ОП) будет, что, как я думал, было точкой зрения Артема. Также оцените тот факт, что TS фактически не использует это для частных полей.
TypeScript будет передавать аргументы IIFE в случаях, когда между классами существует наследование. Например, замыкание ниже используется, когда Greeter расширяет класс BaseGreeter:
var Greeter = /** @class */ (function (_super) {
// __extends is added by the TS transpiler to simulate inheritance
__extends(Greeter, _super);
function Greeter(subject) {
var _this = _super.call(this) || this;
_this.subject = subject;
return _this;
}
Greeter.What = function () {
return "Greater";
};
Greeter.prototype.greet = function () {
return "Hello, " + this.subject;
};
return Greeter;
}(BaseGreeter));
@charlietfl ТС не использует IIFE для скрытия
privateполей, вообще-то. В JS они все общедоступны.