Какова цель самостоятельного выполнения функции в JavaScript?
В javascript, когда вы хотите использовать это:
(function(){
//Bunch of code...
})();
через это:
//Bunch of code...
21 ответ
Это все о переменной области видимости. Переменные, объявленные в самоисполняющейся функции, по умолчанию доступны только для кода внутри самоисполняющейся функции. Это позволяет писать код, не заботясь о том, как называются переменные в других блоках кода JavaScript.
Например:
(function(){
var foo = 3;
alert(foo);
})();
alert(foo);
Сначала будет выдано "3", а затем будет выдано сообщение об ошибке при следующем оповещении, поскольку foo не определен.
Упрощенные. Так выглядит очень нормально, это почти утешительно:
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
Тем не мение. Что если я добавлю на свою страницу действительно удобную библиотеку javascript, которая переводит продвинутые символы в их представления базового уровня?
Чего ждать?
Я имею в виду. Если кто-то вводит символ с каким-то акцентом (например, французский или испанский), но мне нужны только английские символы? Аз в моей программе? Ну... Испанские символы 'n ~' и французский 'e /' (я использовал два символа каждый для них, но вы, вероятно, можете сделать мысленный скачок в символ, который представляет акценты), эти символы могут быть переведены в базовые символы '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.
Я большой поклонник:), потому что:
- Это сводит код к минимуму
- Обеспечивает отделение поведения от представления
- Это обеспечивает закрытие, которое предотвращает конфликты имен
Чрезвычайно - (Почему вы должны сказать, что это хорошо?)
- Речь идет об определении и выполнении функции одновременно.
- Вы могли бы заставить эту самовыполняющуюся функцию возвращать значение и передавать функцию в качестве параметра другой функции.
- Это хорошо для инкапсуляции.
- Это также хорошо для определения объема блока.
- Да, вы можете заключить все ваши файлы.js в самовоспроизводящуюся функцию и предотвратить глобальное загрязнение пространства имен.;)
Больше здесь.
Пространства имен. Области применения JavaScript - на уровне функций.
Я не могу поверить, что ни один из ответов не упоминает подразумеваемые глобалы.
(function(){})()
конструкция не защищает от подразумеваемых глобалов, что для меня является более серьезной проблемой, см. http://yuiblog.com/blog/2006/06/01/global-domination/
По сути, функциональный блок гарантирует, что все зависимые "глобальные переменные", которые вы определили, ограничены вашей программой, он не защищает вас от определения неявных глобальных переменных. JSHint или тому подобное может дать рекомендации о том, как защититься от такого поведения.
Чем лаконичнее var App = {}
синтаксис обеспечивает аналогичный уровень защиты и может быть включен в функциональный блок, когда он находится на "общедоступных" страницах. (см. Ember.js или SproutCore для реальных примеров библиотек, которые используют эту конструкцию)
Так далеко как private
свойства идут, они немного переоценены, если вы не создаете публичную среду или библиотеку, но если вам нужно их реализовать, у Дугласа Крокфорда есть несколько хороших идей.
Я прочитал все ответы, чего-то очень важного здесь не хватает, я поцелую. Есть две основные причины, по которым мне нужны самовыполняющиеся анонимные функции, или, лучше сказать, "Выражение с немедленным вызовом функции (IIFE)":
- Лучшее управление пространством имен (предотвращение загрязнения пространства имен -> JS Module)
- Замыкания (имитация частных членов класса, как известно из ООП)
Первый был объяснен очень хорошо. Для второго, пожалуйста, изучите следующий пример:
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
может иметь некоторое переменное значение (для цикла), и каждый раз, когда есть новая функция.
Область изоляции, может быть. Так что переменные внутри объявления функции не загрязняют внешнее пространство имен.
Конечно, на половине реализаций 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...
Одно из отличий состоит в том, что переменные, которые вы объявляете в функции, являются локальными, поэтому они исчезают при выходе из функции и не конфликтуют с другими переменными в другом коде.
Короткий ответ: предотвратить загрязнение Глобального (или более высокого) масштаба.
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 также может влиять на эффективность и производительность, потому что функция, которая, как ожидается, будет запущена только один раз, будет выполнена один раз, а затем навсегда брошена в пустоту. Это означает, что объявление функции или метода не остается в памяти.
Самоисполняющаяся функция используется для управления областью действия переменной.
Область действия переменной - это область вашей программы, в которой она определена.
Глобальная переменная имеет глобальную область видимости; он определяется везде в вашем коде 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.
Сначала вы должны посетить MDN IIFE. Теперь кое-что об этом
- это выражение немедленного вызова функции. Поэтому, когда ваш файл javascript вызывается из HTML, эта функция вызывается немедленно.
- Это предотвращает доступ к переменным в рамках идиомы IIFE, а также загрязняет глобальную область видимости.
Самостоятельно вызванная функция в javascript:
Вызывающее само выражение вызывается (запускается) автоматически, без вызова. Вызывающее себя выражение вызывается сразу после его создания. Это в основном используется для избежания конфликта имен, а также для достижения инкапсуляции. Переменные или объявленные объекты не доступны вне этой функции. Во избежание проблем минимизации (filename.min) всегда используйте самозапускаемую функцию.
Учитывая ваш простой вопрос: "В 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 в объявлении моей функции, и мне не нужна именованная функция для дальнейшего использования, но мне нужно дождаться этого вызова вставки, или мне нужны другие более богатые функции (кто знает?).
(function(){
var foo = {
name: 'bob'
};
console.log(foo.name); // bob
})();
console.log(foo.name); // Reference error
На самом деле, вышеуказанная функция будет рассматриваться как выражение функции без имени.
Основная цель обертывания функции с закрытыми и открытыми скобками - избежать загрязнения глобального пространства.
Переменные и функции внутри выражения функции стали частными (то есть) они не будут доступны вне функции.
Поскольку функции в Javascript являются объектами первого класса, определяя его таким образом, он эффективно определяет "класс", очень похожий на C++ или C#.
Эта функция может определять локальные переменные и иметь функции внутри нее. Внутренние функции (фактически методы экземпляра) будут иметь доступ к локальным переменным (фактически переменные экземпляра), но они будут изолированы от остальной части сценария.
Использование этой методологии для закрытия. Прочтите эту ссылку , чтобы узнать больше о замыканиях.
Похоже, что на этот вопрос все ответы уже готовы, но я все равно выложу свой вклад.
Я знаю, когда мне нравится использовать самовыполняющиеся функции.
var myObject = {
childObject: new function(){
// bunch of code
},
objVar1: <value>,
objVar2: <value>
}
Функция позволяет мне использовать дополнительный код для определения атрибутов и свойств childObjects для более чистого кода, таких как установка часто используемых переменных или выполнение математических уравнений; Ой! или проверка ошибок. в отличие от того, чтобы быть ограниченным синтаксисом реализации вложенного объекта...
object: {
childObject: {
childObject: {<value>, <value>, <value>}
},
objVar1: <value>,
objVar2: <value>
}
Кодирование в целом имеет много неясных способов делать много одинаковых вещей, заставляя задуматься: "Зачем беспокоиться?" Но появляются новые ситуации, когда вы больше не можете полагаться только на основные / основные принципы.