Вопрос

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

new function() { 
  var code...
}

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

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

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

Это было полезно?

Решение

В обоих случаях функция будет выполняться, единственная реальная разница заключается в том, каким может быть возвращаемое значение выражения и какое значение «this» будет внутри функции.

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

new expression

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

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

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

В общих чертах «новая функция() { ..}» будет работать медленнее из-за необходимости создания объекта this для конструктора.

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

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

Другие советы

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

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

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

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

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

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

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

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

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

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

Привет, внутренняя функция
Привет внешняя функция
Мир внутри функции

...затем вы получите ошибку, поскольку «b» не определен вне функции!

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top