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

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

new function() { 
  var code...
}

и встроенная выполняемая функция :

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

Есть ли различия в поведении между этими двумя? Один «лучше» над другим?

8.08.2008 20:53:21
5 ОТВЕТОВ
РЕШЕНИЕ

В обоих случаях будет выполняться функция, единственное реальное различие заключается в том, каким может быть возвращаемое значение выражения и какое значение «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

10
9.08.2008 01:08:34

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

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

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

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

5
8.08.2008 21:08:38

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

<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 была строкой, которую вернула функция.

0
8.08.2008 22:20:46

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

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

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

Пример:

<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 Функция
Hello снаружи Функция
World Inside Function

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

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

-4
13.11.2011 15:16:01
-1 Это связано с пропуском «var» перед «a», делающим его глобальным и не связанным с вопросом.
Tomas 19.05.2010 13:43:28

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

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

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

3
9.08.2008 02:20:29