В javascript есть два популярных стиля закрытия. Первым вызываю анонимный конструктор:
new function() {
var code...
}
и встроенная выполняемая функция:
(function() {
var code...
})();
есть ли различия в поведении между этими двумя? Одно "лучше" другого?



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


@Lance: первый тоже выполняется. Сравните его с именованным конструктором:
function Blah() {
alert('blah');
}
new Bla();
на самом деле это также выполняет код. То же самое и с анонимным конструктором ...
Но вопрос был не в этом ;-)
Оба случая будут выполнять функцию, единственная реальная разница в том, каким может быть возвращаемое значение выражения и какое значение this будет внутри функции.
В основном поведение
new expression
Фактически эквивалентен
var tempObject = {};
var result = expression.call(tempObject);
if (result is not an object)
result = tempObject;
Хотя, конечно, tempObject и result являются временными значениями, которые вы никогда не увидите (они являются деталями реализации в интерпретаторе), и нет никакого механизма JS для проверки «не является объектом».
Вообще говоря, метод new function () {..} будет работать медленнее из-за необходимости создания объекта this для конструктора.
Тем не менее, это не должно быть реальной разницей, поскольку выделение объектов не является медленным, и вы не должны использовать такой код в горячем коде (из-за стоимости создания объекта функции и связанного с ним закрытия).
Обновлено: я понял, что я упустил из этого то, что tempObject получит прототип expression, например. (до expression.call) tempObject.__proto__ = expression.prototype
Ну я сделал такую страничку:
<html>
<body>
<script type = "text/javascript">
var a = new function() {
alert("method 1");
return "test";
};
var b = (function() {
alert("method 2");
return "test";
})();
alert(a); //a is a function
alert(b); //b is a string containing "test"
</script>
</body>
</html>
Достаточно удивительно (по крайней мере для меня) он предупредил как «метод 1», так и метод 2 ». Я не ожидал, что будет предупрежден« метод 1 ». Разница заключалась в том, какие были значения a и b. A была сама функция, а b - это строка, возвращаемая функцией.
Да, между ними есть различия.
Обе функции являются анонимными и выполняются одинаково. Но разница между ними заключается в том, что во втором случае область действия переменных ограничивается самой анонимной функцией. Невозможно случайно добавить переменные в глобальную область видимости.
Это означает, что, используя второй метод, вы не загромождаете область глобальных переменных, что хорошо, поскольку эти значения глобальных переменных могут мешать некоторым другим глобальным переменным, которые вы можете использовать в какой-либо другой библиотеке или используются в сторонней библиотеке. .
Пример:
<html>
<body>
<script type = "text/javascript">
new function() {
a = "Hello";
alert(a + " Inside Function");
};
alert(a + " Outside Function");
(function() {
var b = "World";
alert(b + " Inside Function");
})();
alert(b + " Outside Function");
</script>
</body>
</html>
В приведенном выше коде результат выглядит примерно так:
Hello Inside Function
Hello Outside Function
World Inside Function
... тогда вы получите сообщение об ошибке, поскольку 'b' не определено вне функции!
Таким образом, я считаю, что второй способ лучше ... безопаснее!
Оба они создают закрытие, выполняя блок кода. Что касается стиля, я предпочитаю вторую по нескольким причинам:
При первом взгляде не сразу видно, что код действительно будет выполнен; строка похоже это создание новая функция, а не выполнение ее как конструктор, но это не то, что на самом деле происходит. Избегайте кода, который не делает того, что, похоже, делает!
Также (function(){ ... })(); делают хорошие маркеры для подставок для книг, так что вы можете сразу увидеть, что вы входите в область закрытия и выходите из нее. Это хорошо, потому что предупреждает читающего программиста об изменении области видимости, и особенно полезно, если вы выполняете некоторую постобработку файла, например, для минификации.
-1 Это происходит из-за того, что опущено «var» перед «a», что делает его глобальным, и не имеет отношения к вопросу.