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

Какая разница в стиле закрытия

В javascript есть два популярных стиля закрытия. Первый я вызываю анонимный конструктор:

new function() { 
  var code...
}

и встроенная функция:

(function() {
  var code...
})();

Существуют ли различия в поведении между этими двумя? Является ли "лучше" над другим?

4b9b3361

Ответ 1

Оба случая будут исполнять функцию, единственная реальная разница - это то, что может быть возвращаемое значение выражения, и какое значение "this" будет внутри функции.

В основном поведение

new expression

Эффективно эквивалентен

var tempObject = {};
var result = expression.call(tempObject);
if (result is not an object)
    result = tempObject;

Хотя, конечно, tempObject и результат являются временными значениями, которые вы никогда не увидите (они являются деталями реализации в интерпретаторе), и нет механизма JS для проверки "не является объектом".

В общем случае метод "new function() {..}" будет медленнее из-за необходимости создания этого объекта для конструктора.

Это говорит о том, что это не должно быть реальным различием, поскольку распределение объектов не является медленным, и вы не должны использовать такой код в горячем коде (из-за стоимости создания объекта функции и связанного с ним закрытия).

Изменить: я понял, что я пропустил это, так как tempObject получит прототип expression, например. (до expression.call) tempObject.__proto__ = expression.prototype

Ответ 2

@Lance: выполняется и первое. Сравните его с именованным конструктором:

function Blah() {
    alert('blah');
}
new Bla();

это также выполняет код. То же самое касается анонимного конструктора...

Но это был не вопрос: -)

Ответ 3

Оба они создают замыкание, выполняя блок кода. В качестве стиля я предпочитаю второй по нескольким причинам:

Не сразу видно, взглянув на первое, что код действительно будет выполнен; строка выглядит так, будто она создает новую функцию, а не выполняет ее как конструктор, но это не то, что на самом деле происходит. Избегайте кода, который не делает то, что он выглядит, как это делает!

Также (function(){... })(); делают приятные жетоны, чтобы вы могли сразу увидеть, что вы входите и оставляете область закрытия. Это хорошо, потому что он предупреждает программиста, читающего его, для изменения области видимости и особенно полезен, если вы выполняете некоторую постобработку файла, например, для минимизации.

Ответ 4

Второй пример выполнит функцию после ее создания.

edit: это не так.

Ответ 5

Ну, я сделал такую ​​страницу:

<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 - строка, возвращаемая функцией.

Ответ 6

Да, между ними есть различия.

Оба являются анонимными функциями и выполняются точно так же. Но разница между ними заключается в том, что во втором случае область переменных ограничена самой анонимной функцией. Нет возможности случайно добавить переменные в глобальную область.

Это означает, что, используя второй метод, вы не загромождаете область глобальных переменных, которая хороша, так как эти значения глобальных переменных могут влиять на некоторые другие глобальные переменные, которые вы можете использовать в какой-либо другой библиотеке или которые используются в сторонняя библиотека.

Пример:

<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>

В приведенном выше коде вывод выглядит примерно так:

Привет, внутренняя функция
Привет, внешняя функция
Функция World Inside

... тогда вы получите сообщение об ошибке, поскольку "b" не определено вне функции!

Таким образом, я считаю, что второй метод лучше... безопаснее!