Зачем встраивать класс JavaScript в анонимную функцию()?
Я читал о новом JavaScript-подобном языке от Microsoft под названием TypeScript. На игровая площадка (раздел примера) существует простой класс в синтаксисе TypeScript, преобразованный в код JavaScript. Исходя из фона программирования Java, мне было интересно узнать, как OOP выполняется в JavaScript как скомпилированный из TypeScript.
Код TypeScript:
class Greeter {
greeting: string;
constructor (message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
var greeter = new Greeter("world");
var button = document.createElement('button')
button.innerText = "Say Hello"
button.onclick = function() {
alert(greeter.greet())
}
document.body.appendChild(button)
И эквивалентный код JavaScript:
var Greeter = (function () {
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
return Greeter;
})();
var greeter = new Greeter("world");
var button = document.createElement('button');
button.innerText = "Say Hello";
button.onclick = function () {
alert(greeter.greet());
};
document.body.appendChild(button);
Часть TypeScript очень похожа на Java, поэтому я это понимаю. Теперь мой вопрос: почему в JavaScript тело класса Greeter
встроено в анонимный вызов function()
?
Почему бы не написать это так?
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
В чем преимущество/недостаток каждого метода?
Ответы
Ответ 1
Ниже вызывается выражение "Вынужденная функция":
(function(){ ... })();
Используется для сохранения глобальной видимости. Хотя в этом случае это не обязательно, поскольку возвращаемое значение присваивается переменной Greeter
. Единственный момент, когда этот шаблон полезен, - это когда вы хотите "private" статические члены.
например:.
var Greeter = (function () {
var foo = 'foo', bar = 'bar'; /* only accessible from function defined
in the local scope ... */
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
return Greeter;
})();
Ответ 2
Помимо очевидных рассуждений о приближении/закрытии. Использование анонимной функции, которая вызывает себя непосредственно, предварительно загружает (интерпретирует) определение класса. Это позволяет оптимизировать JIT-оптимизацию в ходе выполнения. Короче говоря, для более сложных приложений это улучшит производительность.
Ответ 3
Анонимная функция/самозавершение закрытия обычно используется для инкапсуляции области видимости, так что только возвращаемое значение доступно за ее пределами. (или все, что вы прикрепляете к другим объектам, например окну)
Ответ 4
Это разрешено для частных членов. В этом примере все участники являются общедоступными, поэтому ваши две конструкции эквивалентны. Однако, если вы хотите предоставить частным членам, вам нужно скрыть их из области вызова через закрытие. Таким образом, если у вас есть частный член, например:
class Greeter {
private greeting: string;
constructor (message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
Вероятно, вы получили бы что-то вроде этого:
var Greeter = (function () {
var greeting="";
function Greeter(message) {
greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + greeting;
};
return Greeter;
})();
Приветствующая переменная будет доступна для любой функции, определенной внутри анонимной функции, но невидимой везде.
Ответ 5
Возможно, анонимная функция предотвращает совпадение имен с другими частями кода. Подумайте об этом так, внутри своей анонимной функции вы даже можете объявить переменную с именем "$", чтобы быть тем, что хотите, и в то же время использовать jQuery в других частях вашего кода без конфликтов.
Ответ 6
Закрытие является единственным средством вызова конструкторов с параметрами:
var w = new Greeter("hello")
Существуют и другие методы, но все сложные и с ограничениями и недостатками.