В 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;}
? Это установит глобальную переменную, верно?
function(){ var foo = 3; alert(foo); }; alert(foo);
так что я до сих пор не понимаю
Упрощенные. Так выглядит очень нормально, это почти утешительно:
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
Тем не менее, что если я добавлю на свою страницу действительно удобную библиотеку JavaScript, которая переводит продвинутые символы в их представления базового уровня?
Чего ждать?
Я имею в виду, если кто-то печатает символ с каким-то акцентом на нем, но мне нужны только «английские» символы AZ в моей программе? Ну что ж ... Испанские символы «ñ» и французский «é» можно перевести в базовые символы «n» и «e».
Итак, кто-то хороший человек написал всеобъемлющий конвертер символов, который я могу включить в свой сайт ... Я включаю его.
Одна проблема: в нем есть функция с именем name, такая же, как и моя функция.
Это то, что называется столкновением. У нас есть две функции, объявленные в одной области с одним и тем же именем. Мы хотим избежать этого.
Поэтому нам нужно как-то расширить наш код.
Единственный способ использовать код в 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;
}
}
)();
Таким образом, в большинстве учебных пособий, которые вы читаете, вы теперь будете засыпаны термином «анонимный самореализация» или что-то подобное.
После многих лет профессионального развития я настоятельно призываю вас назвать каждую функцию, которую вы пишете для целей отладки.
Когда что-то пойдет не так (и будет), вы будете проверять обратную трассировку в своем браузере. Это всегда легче сократить ваши вопросы кода при записи в трассировке стека имеют имена!
Очень скучный и, надеюсь, это поможет!
:)
Самостоятельный вызов (также известный как автоматический вызов) - это когда функция выполняется сразу после ее определения. Это базовый шаблон и служит основой для многих других шаблонов разработки 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
префикса, поэтому по соглашению он не должен быть заглавными.
Есть ли параметр, и «Куча кода» возвращает функцию?
var a = function(x) { return function() { document.write(x); } }(something);
Закрытие. Значение something
используется функцией, назначенной для a
. something
может иметь некоторое переменное значение (для цикла), и каждый раз, когда есть новая функция.
var x = something;
во внешней функции x
как параметр, хотя: imo это более читабельно таким образом ...
x
и будете зависеть непосредственно от лексической области видимости, то есть document.write(something)
...
Область изоляции, может быть. Так что переменные внутри объявления функции не загрязняют внешнее пространство имен.
Конечно, на половине реализаций JS они все равно будут.
Вот твердый пример того, как само-вызывающая анонимная функция может быть полезна.
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
первого случая будет в порядке.
Поскольку функции в Javascript являются объектами первого класса, определяя его таким образом, он эффективно определяет «класс», очень похожий на C ++ или C #.
Эта функция может определять локальные переменные и иметь функции внутри нее. Внутренние функции (эффективные методы экземпляров) будут иметь доступ к локальным переменным (фактически переменные экземпляров), но они будут изолированы от остальной части сценария.
Самостоятельно вызванная функция в javascript:
Вызывающее себя выражение вызывается (запускается) автоматически, без вызова. Вызывающее себя выражение вызывается сразу после его создания. Это в основном используется для избежания конфликта имен, а также для достижения инкапсуляции. Переменные или объявленные объекты не доступны вне этой функции. Во избежание проблем минимизации (filename.min) всегда используйте самозапускаемую функцию.
Самоисполняющаяся функция используется для управления областью действия переменной.
Область действия переменной - это область вашей программы, в которой она определена.
Глобальная переменная имеет глобальную область видимости; он определяется везде в вашем коде JavaScript и может быть доступен из любого места скрипта, даже в ваших функциях. С другой стороны, переменные, объявленные внутри функции, определяются только в теле функции. Они являются локальными переменными, имеют локальную область видимости и доступны только внутри этой функции. Параметры функции также считаются локальными переменными и определяются только внутри тела функции.
Как показано ниже, вы можете получить доступ к переменной globalvariable внутри вашей функции, а также заметить, что в теле функции локальная переменная имеет приоритет над глобальной переменной с тем же именем.
var globalvar = "globalvar"; // this var can be accessed anywhere within the script
function scope() {
alert(globalvar);
localvar = "localvar" //can only be accessed within the function scope
}
scope();
Таким образом, в основном самовыполняющаяся функция позволяет писать код, не заботясь о том, как называются переменные в других блоках кода javascript.
(function(){
var foo = {
name: 'bob'
};
console.log(foo.name); // bob
})();
console.log(foo.name); // Reference error
На самом деле, вышеприведенная функция будет рассматриваться как выражение функции без имени.
Основная цель обертывания функции с закрытыми и открытыми скобками - избежать загрязнения глобального пространства.
Переменные и функции внутри выражения функции стали частными (то есть) они не будут доступны вне функции.
Короткий ответ: предотвратить загрязнение Глобальной (или более высокой) области.
IIFE (выражения с немедленным вызовом функций) - это лучший метод написания сценариев в виде плагинов, надстроек, пользовательских сценариев или любых других сценариев, которые должны работать со сценариями других людей . Это гарантирует, что любая заданная вами переменная не окажет нежелательного влияния на другие сценарии.
Это другой способ написать выражение IIFE. Я лично предпочитаю следующий метод:
void function() {
console.log('boo!');
// expected output: "boo!"
}();
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void
Из приведенного выше примера очень ясно, что IIFE также может влиять на эффективность и производительность, потому что функция, которая должна запускаться только один раз, будет выполнена один раз, а затем навсегда выгружена в пустоту . Это означает, что объявление функции или метода не остается в памяти.
void
раньше. Мне это нравится.
Сначала вы должны посетить MDN IIFE , теперь некоторые моменты по этому поводу
Похоже, что на этот вопрос все ответы уже готовы, но я все равно выложу свой вклад.
Я знаю, когда мне нравится использовать самовыполняющиеся функции.
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 позволяет создавать частные свойства и методы.