В javascript, когда вы хотите использовать это:
(function(){
//Bunch of code...
})();
через это:
//Bunch of code...
В javascript, когда вы хотите использовать это:
(function(){
//Bunch of code...
})();
через это:
//Bunch of code...
Все дело в области видимости переменных. Переменные, объявленные в самоисполняющейся функции, по умолчанию доступны только для кода внутри самоисполняющейся функции. Это позволяет писать код, не заботясь о том, как именуются переменные в других блоках кода JavaScript.
Например, как упоминалось в комментарии Александра:
(function() {
var foo = 3;
console.log(foo);
})();
console.log(foo);
Сначала будет регистрироваться 3
, а на следующем console.log
будет выдана ошибка, поскольку foo
не определен.
var
, вот так: ...function(){ foo=3;}
? Он бы установил глобальную переменную, не так ли?
- person T.Todua; 25.11.2016
function(){ var foo = 3; alert(foo); }; alert(foo);
Так что я до сих пор не понимаю
- person João Pimentel Ferreira; 03.12.2017
{ let foo = 3 }
?
- person Giulio; 20.08.2020
Упрощенно. Так нормально выглядит, это почти утешает:
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
Однако что, если я добавлю на свою страницу действительно удобную библиотеку javascript, которая переводит продвинутые символы в их представления базового уровня?
Чего ждать?
Я имею в виду, если кто-то набирает иероглиф с каким-то акцентом, но мне нужны только «английские» символы A-Z в моей программе? Что ж ... Испанские символы «ñ» и французские символы «é» могут быть переведены в базовые символы «n» и «e».
Итак, кто-то хороший человек написал всеобъемлющий конвертер символов, который я могу включить на свой сайт ... Я включаю его.
Одна проблема: в нем есть функция, называемая «имя», как и моя функция.
Это то, что называется столкновением. У нас есть две функции, объявленные в одной области действия с одинаковым именем. Мы хотим этого избежать.
Итак, нам нужно как-то расширить наш код.
Единственный способ ограничить код в javascript - обернуть его функцией:
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
Это могло бы решить нашу проблему. Теперь все заключено и доступно только через открывающую и закрывающую фигурные скобки.
У нас есть функция в функции ... что странно на вид, но полностью законно.
Только одна проблема. Наш код не работает. Наша переменная userName никогда не отображается в консоли!
Мы можем решить эту проблему, добавив вызов нашей функции после существующего блока кода ...
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
main();
Или раньше!
main();
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
Второстепенная проблема: каковы шансы, что имя «основной» еще не использовалось? ... такой очень, очень тонкий.
Нам нужно БОЛЬШЕ масштабирования. И какой-то способ автоматически выполнить нашу функцию main ().
Теперь мы переходим к функциям автоматического выполнения (или самовыполняющимся, самовыполняющимся и т. Д.).
((){})();
Синтаксис грубоват как грех. Однако это работает.
Когда вы заключаете определение функции в круглые скобки и включаете список параметров (другой набор или круглые скобки!), Оно действует как вызов функции.
Итак, давайте снова посмотрим на наш код с некоторым самоисполняющимся синтаксисом:
(function main() {
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
)();
Итак, в большинстве учебных пособий, которые вы читаете, вас будут засыпать термином «анонимное самовыполнение» или чем-то подобным.
После многих лет профессионального развития я настоятельно призываю вас называть каждую функцию, которую вы пишете, для целей отладки.
Когда что-то пойдет не так (а это произойдет), вы будете проверять обратную трассировку в своем браузере. Когда записи в трассировке стека имеют имена, всегда легче сузить круг проблем с кодом!
Очень многословный, и я надеюсь, что это поможет!
:)
- person João Pimentel Ferreira; 03.12.2017
Самовызов (также известный как автоматический вызов) - это когда функция выполняется сразу после ее определения. Это базовый шаблон, который служит основой для многих других шаблонов разработки JavaScript.
Я большой поклонник этого :) потому что:
Чрезвычайно - (Почему ты должен говорить, что это хорошо?)
Подробнее см. здесь.
Пространство имен. Области видимости JavaScript являются функциональными.
Я не могу поверить, что ни в одном из ответов не упоминаются подразумеваемые глобалы.
Конструкция (function(){})()
не защищает от подразумеваемых глобальных переменных, что для меня является большей проблемой, см. http://yuiblog.com/blog/2006/06/01/global-domination/
По сути, функциональный блок гарантирует, что все зависимые "глобальные переменные", которые вы определили, ограничены вашей программой, он не защищает вас от определения неявных глобальных переменных. JSHint и т.п. могут предоставить рекомендации о том, как защититься от такого поведения.
Более лаконичный синтаксис var App = {}
обеспечивает аналогичный уровень защиты и может быть заключен в функциональный блок на «общедоступных» страницах. (см. Ember.js или SproutCore для реальных примеров библиотек, использующих эту конструкцию)
Что касается свойств private
, они отчасти переоценены, если вы не создаете общедоступную структуру или библиотеку, но если вам нужно их реализовать, У Дугласа Крокфорда есть несколько хороших идей.
Я прочитал все ответы, здесь не хватает чего-то очень важного, ПОЦЕЛУЮ. Есть две основные причины, по которым мне нужны самозаполняющиеся анонимные функции, или, лучше сказать, «Выражение немедленного вызова функции (IIFE)»:
Первый объяснен очень хорошо. Для второго, пожалуйста, изучите следующий пример:
var MyClosureObject = (function (){
var MyName = 'Michael Jackson RIP';
return {
getMyName: function () { return MyName;},
setMyName: function (name) { MyName = name}
}
}());
Внимание 1: мы не назначаем функцию MyClosureObject
, более того, результат вызова этой функции. Обратите внимание на ()
в последней строке.
Внимание 2: Что вам дополнительно нужно знать о функциях в Javascript, так это то, что внутренние функции получают доступ к параметрам и переменным функций, в которых они определены.
Попробуем поэкспериментировать:
Я могу получить MyName
, используя getMyName
, и он работает:
console.log(MyClosureObject.getMyName());
// Michael Jackson RIP
Следующий простодушный подход не сработает:
console.log(MyClosureObject.MyName);
// undefined
Но я могу задать другое имя и получить ожидаемый результат:
MyClosureObject.setMyName('George Michael RIP');
console.log(MyClosureObject.getMyName());
// George Michael RIP
Изменить: В приведенном выше примере MyClosureObject
предназначен для использования без префикса new
, поэтому по соглашению он не должен быть написан с заглавной буквы.
Возможно, изоляция области действия. Чтобы переменные внутри объявления функции не загрязняли внешнее пространство имен.
Конечно, в половине реализаций JS они все равно будут.
Есть ли параметр, а «Связка кода» возвращает функцию?
var a = function(x) { return function() { document.write(x); } }(something);
Закрытие. Значение something
используется функцией, назначенной a
. something
может иметь различное значение (для цикла) и каждый раз, когда a имеет новую функцию.
var x = something;
во внешней функции, а не x
в качестве параметра, хотя: я думаю, это более читабельно ...
- person Christoph; 27.02.2009
x
и напрямую зависит от лексической области, т.е. _2 _...
- person Christoph; 27.02.2009
Вот наглядный пример того, как может быть полезна самозапускающаяся анонимная функция.
for( var i = 0; i < 10; i++ ) {
setTimeout(function(){
console.log(i)
})
}
Выход: 10, 10, 10, 10, 10...
for( var i = 0; i < 10; i++ ) {
(function(num){
setTimeout(function(){
console.log(num)
})
})(i)
}
Выход: 0, 1, 2, 3, 4...
let
вместо var
в первом случае все будет в порядке.
- person Vitaly Zdanevich; 21.09.2018
Одно отличие состоит в том, что переменные, которые вы объявляете в функции, являются локальными, поэтому они исчезают при выходе из функции и не конфликтуют с другими переменными в другом или том же коде.
Сначала вы должны посетить MDN IIFE. Теперь кое-что об этом
Самостоятельно выполняющиеся функции используются для управления областью переменной.
Область видимости переменной - это область вашей программы, в которой она определена.
Глобальная переменная имеет глобальную область видимости; он определен повсюду в вашем коде JavaScript и может быть доступен из любого места внутри скрипта, даже в ваших функциях. С другой стороны, переменные, объявленные внутри функции, определяются только в теле функции. Они являются локальными переменными, имеют локальную область видимости и доступны только внутри этой функции. Параметры функции также считаются локальными переменными и определяются только в теле функции.
Как показано ниже, вы можете получить доступ к переменной глобальных переменных внутри своей функции, а также отметить, что в теле функции локальная переменная имеет приоритет над глобальной переменной с тем же именем.
var globalvar = "globalvar"; // this var can be accessed anywhere within the script
function scope() {
alert(globalvar);
var localvar = "localvar"; //can only be accessed within the function scope
}
scope();
Таким образом, в основном самоисполняющаяся функция позволяет писать код, не заботясь о том, как именуются переменные в других блоках кода javascript.
Поскольку функции в Javascript являются объектами первого класса, определяя его таким образом, он фактически определяет «класс» во многом так же, как C ++ или C #.
Эта функция может определять локальные переменные и иметь внутри себя функции. Внутренние функции (фактически методы экземпляра) будут иметь доступ к локальным переменным (фактически переменным экземпляра), но они будут изолированы от остальной части скрипта.
Самостоятельно запускаемая функция в javascript:
Самозапускающееся выражение вызывается (запускается) автоматически, но не вызывается. Самозапускающееся выражение вызывается сразу после его создания. Это в основном используется для предотвращения конфликта имен, а также для достижения инкапсуляции. Переменные или объявленные объекты недоступны вне этой функции. Во избежание проблем с минимизацией (filename.min) всегда используйте самовыполняемую функцию.
(function(){
var foo = {
name: 'bob'
};
console.log(foo.name); // bob
})();
console.log(foo.name); // Reference error
Фактически, указанная выше функция будет рассматриваться как выражение функции без имени.
Основная цель заключения функции закрывающими и открытыми круглыми скобками - избежать загрязнения глобального пространства.
Переменные и функции внутри выражения функции стали закрытыми (т.е. они не будут доступны вне функции).
Краткий ответ: для предотвращения загрязнения Глобального (или более высокого) масштаба.
IIFE (Immediately Invoked Function Expressions) - лучший метод для написания скриптов в виде надстроек, надстроек, пользовательских скриптов или любых других скриптов, которые, как ожидается, будут работать со скриптами других людей. Это гарантирует, что любая определяемая вами переменная не окажет нежелательного воздействия на другие скрипты.
Это другой способ написать выражение IIFE. Лично я предпочитаю следующий метод:
void function() {
console.log('boo!');
// expected output: "boo!"
}();
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void
Из приведенного выше примера очень ясно, что IIFE также может влиять на эффективность и производительность, потому что функция, которая, как ожидается, будет запущена только один раз, будет выполнена один раз, а затем навсегда выброшена в пустоту. Это означает, что объявление функции или метода не остается в памяти.
void
. Мне это нравится.
- person Ej.; 20.12.2019
Похоже, что на этот вопрос уже есть готовый ответ, но я все равно опубликую свой отзыв.
Я знаю, когда мне нравится использовать самоисполняющиеся функции.
var myObject = {
childObject: new function(){
// bunch of code
},
objVar1: <value>,
objVar2: <value>
}
Эта функция позволяет мне использовать некоторый дополнительный код для определения атрибутов и свойств childObjects для более чистого кода, таких как установка часто используемых переменных или выполнение математических уравнений; Ой! или проверка ошибок. в отличие от синтаксиса создания экземпляров вложенных объектов ...
object: {
childObject: {
childObject: {<value>, <value>, <value>}
},
objVar1: <value>,
objVar2: <value>
}
В кодировании вообще есть много неясных способов делать много одних и тех же вещей, что заставляет задуматься: «Зачем беспокоиться?» Но продолжают появляться новые ситуации, когда вы больше не можете полагаться только на базовые / основные принципы.
Учитывая ваш простой вопрос: «В javascript, когда вы хотите использовать это: ...»
Мне нравятся ответы @ken_browning и @ sean_holding, но вот еще один вариант использования, о котором я не упоминал:
let red_tree = new Node(10);
(async function () {
for (let i = 0; i < 1000; i++) {
await red_tree.insert(i);
}
})();
console.log('----->red_tree.printInOrder():', red_tree.printInOrder());
где Node.insert - какое-то асинхронное действие.
Я не могу просто вызвать await без ключевого слова async в объявлении моей функции, и мне не нужна именованная функция для дальнейшего использования, но мне нужно дождаться этого вызова вставки, или мне нужны другие более богатые функции (кто знает?) .
IIRC позволяет создавать частные свойства и методы.
{ }
с директивой"use strict";
, а при объявлении переменных и ссылок на функции использовать ключевое словоlet
вместоvar
. - person caiohamamura   schedule 11.05.2021