В чем разница в стиле закрытия?

В JavaScript есть два популярных стиля замыкания. Первый я называю анонимным конструктором:
new function() {
var code...
}
и встроенная выполняемая функция:
(function() {
var code...
})();
есть ли разница в поведении между этими двумя? Один «лучше» другого?
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 получит прототип выражения, например (до вызова выражения) 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>
В приведенном выше коде вывод будет примерно таким:
Hello Inside Function
Hello Outside Function
World Inside Function
... затем вы получите ошибку, так как «b» не определено вне функции!
Поэтому я считаю, что второй способ лучше... безопаснее!
Это связано с тем, что перед «a» опущено «var», что делает его глобальным и не имеет отношения к вопросу.
Получение текста из выпадающего списка
Это возвращает значение того, что выбрано в моем выпадающем меню. document.getElementById('newSkill').value Однако я не могу найти, какое свойство использовать для текста, который в данный момент отображается в раскрывающемся меню. Я попробовал "text", но это не дало ответа, кто-нибудь здесь знает? Для тех, кто не уверен, вот HTML-код раскрывающегося списка. <select name="newSkill" id="newSkill"> <option value="1">A skill</option> <option value="2">Another skill</option> <option value="3">Yet another skill</option> </select> На основе вашего примера HTML-кода вот один из способов получить отображаемый текст выбранного в данный момент параметра: var skillsSelect = document.getElementById("newSkill"); var selectedText = skillsSelect.options[skillsSelect.selectedIndex].text; Для тех, кто…
JavaScript должен запускаться при отображении ModalPopupExtender
ASP _ NET AJAX ModalPopupExtender имеет свойства OnCancelScript и OnOkScript, но, похоже, не имеет свойства OnShowScript. Я хотел бы указать функцию javascript для запуска каждый раз, когда отображается всплывающее окно. В прошлых ситуациях я устанавливал фиктивный элемент управления TargetControlID и предоставлял свой собственный элемент управления, который сначала выполняет некоторый код JS, а затем использует методы JS для отображения всплывающего окна. Но в этом случае я показываю всплывающее окно как из клиентского, так и из серверного кода. Кто-нибудь знает, как это сделать? Кстати, мне это было нужно, потому что у меня есть…
У меня есть объект JavaScript. Есть ли встроенный или общепринятый способ получить длину этого объекта? const myObject = new Object(); myObject["firstname"] = "Gareth"; myObject["lastname"] = "Simpson"; myObject["age"] = 21; Это отчасти правда, но так много людей привыкли к «ассоциативному массиву» PHP, что они могут предположить, что это означает «упорядоченную ассоциативную карту», хотя объекты JS на самом деле…