Какая разница в стиле закрытия - PullRequest
20 голосов
/ 09 августа 2008

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

new function() { 
  var code...
}

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

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

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

Ответы [ 6 ]

9 голосов
/ 09 августа 2008

Функция будет выполняться в обоих случаях, единственная реальная разница в том, каким может быть возвращаемое значение выражения и какое значение "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 s, например. (до expression.call) tempObject.__proto__ = expression.prototype

5 голосов
/ 09 августа 2008

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

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

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

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

3 голосов
/ 09 августа 2008

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

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

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

0 голосов
/ 09 августа 2008

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

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

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

Пример:

<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
Привет Снаружи Функция
Мир внутри Функция

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

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

0 голосов
/ 09 августа 2008

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

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

0 голосов
/ 09 августа 2008

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

изменить: это не совсем так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...