Что такое конструкция (function() { })() в JavaScript?

Раньше я знал, что это значит, но сейчас я борюсь...

Это в основном говорит document.onload?

(function () {

})();

30 ответов

Решение

Это выражение с немедленным вызовом функции, или сокращенно IIFE. Он выполняется сразу после его создания.

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

Этот шаблон часто используется при попытке избежать загрязнения глобального пространства имен, потому что все переменные, используемые внутри IIFE (как и в любой другой нормальной функции), не видны за пределами его области действия.
Вот почему, может быть, вы перепутали эту конструкцию с обработчиком событий для window.onloadпотому что это часто используется как это:

(function(){
    // all your code here
    var foo = function() {};
    window.onload = foo;
    // ...
})();
// foo is unreachable here (it’s undefined)

Исправление, предложенное Guffa:

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

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

Это так же, как если бы вы присвоили его переменной и использовали сразу после этого, только без переменной:

var f = function () {
};
f();

В jQuery есть похожая конструкция, о которой вы можете подумать:

$(function(){
});

Это короткая форма связывания ready событие:

$(document).ready(function(){
});

Вызов функции с немедленным вызовом (IIFE) немедленно вызывает функцию. Это просто означает, что функция выполняется сразу после завершения определения.

Еще три общие формулировки:

// Crockford's preference - parens on the inside
(function() {
  console.log('Welcome to the Internet. Please follow me.');
}());

//The OPs example, parentheses on the outside
(function() {
  console.log('Welcome to the Internet. Please follow me.');
})();

//Using the exclamation mark operator
//https://stackru.com/a/5654929/1175496
!function() {
  console.log('Welcome to the Internet. Please follow me.');
}();

Если нет особых требований к его возвращаемому значению, тогда мы можем написать:

!function(){}();  // => true
~function(){}(); // => -1
+function(){}(); // => NaN
-function(){}();  // => NaN

В качестве альтернативы это может быть:

~(function(){})();
void function(){}();
true && function(){ /* code */ }();
15.0, function(){ /* code */ }();

Вы даже можете написать:

new function(){ /* code */ }
31.new function(){ /* code */ }() //If no parameters, the last () is not required

Эта конструкция называется выражением немедленного вызова функции (IIFE), что означает, что она выполняется немедленно. Думайте об этом как о функции, вызываемой автоматически, когда интерпретатор достигает этой функции.

Наиболее распространенный вариант использования:

Одним из наиболее распространенных вариантов использования является ограничение области действия переменной, созданной с помощью var, Переменные, созданные с помощью var область действия ограничена функцией, поэтому эта конструкция (которая является оболочкой функции для определенного кода) будет следить за тем, чтобы область переменных не выходила из этой функции.

В следующем примере, счетчик не будет доступен за пределами немедленно вызванной функции, т.е. count не будет вытекать из функции. Вы должны получить Reference Error, если вы попытаетесь получить к нему доступ вне немедленно вызванной функции в любом случае.

(function () { 
    var count = 10;
})();
console.log(count);  // Reference Error: count is not defined

ES6 Альтернатива (рекомендуется)

В ES6 теперь мы можем создавать переменные с помощью let а также const, Оба они имеют блочную область (в отличие от var который является функциональной областью).

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

{ 
    let count = 10;
};
console.log(count);  // Reference Error: count is not defined

В этом примере мы использовали let определить count переменная, которая делает count ограничено блоком кода, мы создали с помощью фигурных скобок {...},

Я называю это Curly Jail,

Он объявляет анонимную функцию, а затем вызывает ее:

(function (local_arg) {
   // anonymous function
   console.log(local_arg);
})(arg);

То есть выполнить немедленно.

так что если я сделаю:

var val = (function(){
     var a = 0;  // in the scope of this function
     return function(x){
         a += x;
         return a;
     };
})();

alert(val(10)); //10
alert(val(11)); //21

Скрипка: http://jsfiddle.net/maniator/LqvpQ/


Второй пример:

var val = (function(){
     return 13 + 5;
})();

alert(val); //18
(function () {
})();

Это называется IIFE (выражение для немедленного вызова функции). Один из известных шаблонов дизайна javascript, и это сердце и душа современного шаблона дня. Как следует из названия, он выполняется сразу после его создания. Этот шаблон создает изолированную или закрытую область исполнения.

JavaScript до ECMAScript 6, использующий лексическую область видимости, IIFE используется для имитации определения объема блока. (При использовании ECMAScript 6 возможна блок-область с введением ключевых слов let и const.) Ссылка на проблему с лексической областью видимости

Имитировать блокобзор с помощью IIFE

Преимущество производительности при использовании IIFE заключается в возможности передавать обычно используемые глобальные объекты, такие как окно, документ и т. Д., В качестве аргумента за счет уменьшения поиска в области. (Помните, что Javascript ищет свойства в локальной области и поднимает цепочку до глобальной области). Таким образом, получая доступ к глобальным объектам в локальной области, сократите время поиска, как показано ниже.

(function (globalObj) {
//Access the globalObj
})(window);

Это выражение для немедленного вызова функции в Javascript:

Чтобы понять IIFE в JS, давайте разберем его:

  1. Выражение: то, что возвращает значение
    Пример. Попробуйте выполнить следующие действия в консоли Chrome. Это выражения в JS.
a = 10 
output = 10 
(1+3) 
output = 4
  1. Выражение функции:
    Пример:
// Function Expression 
var greet = function(name){
   return 'Namaste' + ' ' + name;
}

greet('Santosh');

Как работает выражение функции:
- Когда механизм JS запускается впервые (контекст выполнения - фаза создания), эта функция (справа от = выше) не выполняется и не сохраняется в памяти. Переменной 'greet' присваивается 'неопределенное' значение с помощью механизма JS.
- Во время выполнения (контекст выполнения - фаза выполнения) объект функции создается "на лету" (он еще не выполнен), ему присваивается переменная "greet", и его можно вызывать с помощью "greet(" somename ")".

3. Сразу же вызванное выражение функции:

Пример:

// IIFE
var greeting = function(name) {
    return 'Namaste' + ' ' + name;
}('Santosh')

console.log(greeting)  // Namaste Santosh. 

Как работает IIFE:
- Обратите внимание на '()' сразу после объявления функции. К каждому объекту функции прикреплено свойство CODE, которое можно вызывать. И мы можем вызвать его (или вызвать) с помощью скобок '()'.
- Таким образом, здесь, во время выполнения (Контекст выполнения - Фаза выполнения), объект функции создается и выполняется одновременно - Так что теперь переменная приветствия вместо объекта функции имеет возвращаемое значение (строку)

Типичный пример использования IIFE в JS:

Следующий шаблон IIFE довольно часто используется.

// IIFE 
// Spelling of Function was not correct , result into error
(function (name) {
   var greeting = 'Namaste';
   console.log(greeting + ' ' + name);
})('Santosh');
  • мы делаем две вещи здесь а) Завершение выражения нашей функции внутри фигурных скобок (). Это говорит синтаксическому синтаксическому анализатору, что все, что находится внутри (), является выражением (в данном случае выражением функции) и является допустимым кодом.
    б) Мы вызываем эту функцию одновременно, используя () в конце.

Таким образом, эта функция создается и выполняется одновременно (IIFE).

Важный сценарий использования IIFE:

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

Предположим, у меня есть другой файл JS (test1.js), используемый в моей заявке вместе с iife.js (см. Ниже).

// test1.js

var greeting = 'Hello';

// iife.js
// Spelling of Function was not correct , result into error
(function (name) { 
   var greeting = 'Namaste';
   console.log(greeting + ' ' + name);
})('Santosh');

console.log(greeting)   // No collision happens here. It prints 'Hello'.

Таким образом, IIFE помогает нам писать безопасный код, где мы не сталкиваемся с глобальными объектами непреднамеренно.

Нет, эта конструкция просто создает область для именования. Если разбить его по частям, вы увидите, что у вас есть внешний

(...)();

Это вызов функции. Внутри скобки у вас есть:

function() {}

Это анонимная функция. Все, что объявлено с помощью var внутри конструкции, будет видно только внутри той же конструкции и не будет загрязнять глобальное пространство имен.

Это вызывающая себя анонимная функция.

Ознакомьтесь с объяснением W3Schools по поводу функции, вызывающей себя.

Выражения функций могут быть сделаны "самовывозами".

Вызывающее само выражение вызывается (запускается) автоматически, без вызова.

Выражения функций будут выполняться автоматически, если за выражением следует ().

Вы не можете самостоятельно вызывать объявление функции.

Это вызывающая себя анонимная функция. Он выполняется, пока он определен. Это означает, что эта функция определена и вызывает себя сразу после определения.

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

(function(obj){
    // Do something with this obj
})(object);

Здесь "объект", который вы передаете, будет доступен внутри функции как "obj", так как вы захватываете его в сигнатуре функции.

Начни здесь:

var b = 'bee';
console.log(b);  // global

Поместите это в функцию, и она больше не будет глобальной - ваша основная цель.

function a() {
  var b = 'bee';
  console.log(b);
}
a();
console.log(b);  // ReferenceError: b is not defined -- *as desired*

Вызовите функцию немедленно - упс:

function a() {
  var b = 'bee';
  console.log(b);
}();             // SyntaxError: Expected () to start arrow function, but got ';' instead of '=>'

Используйте скобки, чтобы избежать синтаксической ошибки:

(function a() {
  var b = 'bee';
  console.log(b);
})(); // OK now

Вы можете не указывать имя функции:

(function () {    // no name required
  var b = 'bee';
  console.log(b);
})();

Это не должно быть более сложным, чем это.

Это функциональное выражение, оно расшифровывается как Immediately Invoked Function Expression (IIFE). IIFE - это просто функция, которая выполняется сразу после создания. Таким образом, если функция должна ждать, пока ее вызовут для выполнения, IIFE выполняется немедленно. Построим IIFE на примере. Предположим, у нас есть функция сложения, которая принимает два целых числа в качестве аргументов и возвращает сумму, что позволяет превратить функцию сложения в IIFE,

Шаг 1. Определите функцию

function add (a, b){
    return a+b;
}
add(5,5);

Шаг 2. Вызов функции, заключив все объявление функции в круглые скобки.

(function add (a, b){
    return a+b;
})
//add(5,5);

Шаг 3: Чтобы вызвать функцию немедленно, просто удалите текст "добавить" из вызова.

(function add (a, b){
    return a+b;
})(5,5);

Основная причина использования IFFE - сохранить частную область видимости в вашей функции. Внутри вашего кода javascript вы хотите убедиться, что вы не переопределяете какие-либо глобальные переменные. Иногда вы можете случайно определить переменную, которая переопределяет глобальную переменную. Попробуем на примере. Предположим, у нас есть html-файл с именем iffe.html, а коды внутри тега body -

<body>
    <div id = 'demo'></div>
    <script>
        document.getElementById("demo").innerHTML = "Hello JavaScript!";
    </script> 
</body>

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

<body>
    <div id = 'demo'></div>
    <script>
        document.getElementById("demo").innerHTML = "Hello JavaScript!";
        const document = "hi there";
        console.log(document);
    </script> 
</body>

вы получите ошибку SyntaxError: повторное объявление не настраиваемого документа глобального свойства.

Но если вы желаете удалить документ с именем переменной, вы можете сделать это с помощью IFFE.

<body>
    <div id = 'demo'></div>
    <script>
        (function(){
            const document = "hi there";
            this.document.getElementById("demo").innerHTML = "Hello JavaScript!";
            console.log(document);
        })();
        document.getElementById("demo").innerHTML = "Hello JavaScript!";
    </script> 
</body>

Выход:

Давайте попробуем на другом примере, предположим, что у нас есть объект калькулятора, как показано ниже.

<body>
    <script>
        var calculator = {
            add:function(a,b){
                return a+b;
            },
            mul:function(a,b){
                return a*b;
            }
        }
        console.log(calculator.add(5,10));
    </script> 
</body>

Что ж, это работает как шарм, что, если мы случайно переназначим значение объекта калькулятора.

<body>
    <script>
        var calculator = {
            add:function(a,b){
                return a+b;
            },
            mul:function(a,b){
                return a*b;
            }
        }
        console.log(calculator.add(5,10));
        calculator = "scientific calculator";
        console.log(calculator.mul(5,5));
    </script> 
</body>

да, вы получите ошибку TypeError: Calculator.mul не является функцией iffe.html

Но с помощью IFFE мы можем создать частную область видимости, где мы можем создать другой калькулятор имени переменной и использовать его;

<body>
    <script>
        var calculator = {
            add:function(a,b){
                return a+b;
            },
            mul:function(a,b){
                return a*b;
            }
        }
        var cal = (function(){
            var calculator = {
                sub:function(a,b){
                    return a-b;
                },
                div:function(a,b){
                    return a/b;
                }
            }
            console.log(this.calculator.mul(5,10));
            console.log(calculator.sub(10,5));
            return calculator;
        })();
        console.log(calculator.add(5,10));
        console.log(cal.div(10,5));
    </script> 
</body>

Выход:

TL;DR: Выражения могут быть заключены в круглые скобки, что может конфликтовать с вызовом функции, если выражение и блочные формы function были объединены.

Мне нравятся контрпримеры, потому что они рисуют прекрасную картину логики, и никто другой не перечислил их. Вы можете спросить: "Почему браузер не видит function(){}() и просто предположить, что это выражение? »Давайте сопоставим проблему с тремя примерами.

Здесь неоднозначно, (x) во второй строке вызывает функцию из предыдущей строки или является ли это аргументами функции для стрелочной функции.

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

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

Код

var same_name = 1;

var myVar = (function() {
    var same_name = 2;
    console.log(same_name);
})();

console.log(same_name);

производит этот вывод:

2
1

Используя этот синтаксис, вы избегаете столкновения с глобальными переменными, объявленными в другом месте вашего кода JavaScript.

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

(function () {
  function Question(q,a,c) {
    this.q = q;
    this.a = a;
    this.c = c;
  }

  Question.prototype.displayQuestion = function() {
    console.log(this.q);
    for (var i = 0; i < this.a.length; i++) {
      console.log(i+": "+this.a[i]);
    }
  }

  Question.prototype.checkAnswer = function(ans) {
    if (ans===this.c) {
      console.log("correct");
    } else {
      console.log("incorrect");
    }
  }

  var q1 = new Question('Is Javascript the coolest?', ['yes', 'no'], 0);
  var q2 = new Question('Is python better than Javascript?', ['yes', 'no', 'both are same'], 2);
  var q3 = new Question('Is Javascript the worst?', ['yes', 'no'], 1);

  var questions = [q1, q2, q3];

  var n = Math.floor(Math.random() * questions.length)

  var answer = parseInt(prompt(questions[n].displayQuestion()));
  questions[n].checkAnswer(answer);
})();

Самоисполняющаяся анонимная функция. Он выполняется, как только он создан.

Один короткий и фиктивный пример, где это полезно:

function prepareList(el){
  var list = (function(){
    var l = []; 
    for(var i = 0; i < 9; i++){
     l.push(i);
    }
    return l;
  })();

  return function (el){
    for(var i = 0, l = list.length; i < l; i++){
      if(list[i] == el) return list[i];
    }
    return null;
  }; 
} 

var search = prepareList();
search(2);
search(3);

Таким образом, вместо создания списка каждый раз, вы создаете его только один раз (меньше накладных расходов).

Здесь уже много хороших ответов, но вот мои 2 цента:p


Вы можете использовать IIFE (выражение немедленного вызова функции) для:

  1. Избегайте загрязнения глобального пространства имен.

    Переменные, определенные в IIFE (или даже в любой нормальной функции), не перезаписывают определения в глобальной области видимости.

  2. Защита кода от доступа внешнего кода.

    Все, что вы определяете в IIFE, доступно только в IIFE. Он защищает код от изменения внешним кодом. Только то, что вы явно возвращаете как результат функции или устанавливаете как значение для внешних переменных, доступно внешнему коду.

  3. Избегайте именования функций, которые вам не нужно использовать повторно. Хотя можно использовать именованную функцию в шаблоне IIFE, вы этого не делаете, поскольку, как правило, нет необходимости вызывать ее повторно.

  4. Для универсальных определений модулей, которые используются во многих библиотеках JS. Проверьте этот вопрос для подробностей.


IIFE обычно используется следующим образом:

       (function(param){
   //code here
})(args);

Вы можете опустить круглые скобки () вокруг анонимной функции и использования void оператор перед анонимной функцией.

       void function(param){
   //code here
}(args);

Еще один вариант использования - это запоминание, когда объект кэша не является глобальным:

var calculate = (function() {
  var cache = {};
  return function(a) {

    if (cache[a]) {
      return cache[a];
    } else {
      // Calculate heavy operation
      cache[a] = heavyOperation(a);
      return cache[a];
    }
  }
})();

IIFE (немедленно вызванное выражение функции) - это функция, которая выполняется, как только скрипт загружается и уходит.

Рассмотрим функцию, написанную ниже, в файле с именем iife.js

(function(){
       console.log("Hello Stackru!");
   })();

Этот код выше будет выполняться, как только вы загрузите iife.js и напечатает "Hello Stackru!". на консоли инструментов разработчика.

Подробное объяснение см. В разделе " Вызов функции с немедленным вызовом" (IIFE).

Следующий код:

(function () {

})();

называется выражением функции, вызываемой немедленно (IIFE).

Это называется выражением функции, потому что ( yourcode ) оператор в Javascript заставить его в выражении. Разница между выражением функции и объявлением функции заключается в следующем:

// declaration:
function declaredFunction () {}

// expressions:

// storing function into variable
const expressedFunction = function () {}

// Using () operator, which transforms the function into an expression
(function () {})

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

После того, как у нас есть выражение, которое оценивает объект функции, мы можем немедленно вызвать объект функции с () оператор. Например:

(function() {

  const foo = 10;        // all variables inside here are scoped to the function block
  console.log(foo);

})();

console.log(foo);  // referenceError foo is scoped to the IIFE

Почему это полезно?

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

Выражение немедленно вызванной функции (IIFE) - это функция, которая выполняется сразу после ее создания. Он не связан ни с какими событиями или асинхронным выполнением. Вы можете определить IIFE, как показано ниже:

(function() {
     // all your code here
     // ...
})();

Первая пара скобок function(){...} преобразует код внутри скобок в выражение. Вторая пара скобок вызывает функцию, полученную из выражения.

IIFE также может быть описан как самовывозная анонимная функция. Его наиболее распространенное использование - это ограничение области действия переменной, создаваемой через var, или инкапсуляция контекста, чтобы избежать конфликтов имен.

Это анонимная функция, которая вызывает себя. Общеизвестно, как выражение для немедленного вызова функций (IIFE).

Эта функция называется самозапускающейся функцией. Самозапускающаяся (также называемая самовыполняющейся) функция - это безымянная (анонимная) функция, которая вызывается (вызывается) сразу после своего определения. Подробнее здесь

Что делают эти функции, так это то, что когда функция определена, функция вызывается немедленно, что экономит время и дополнительные строки кода (по сравнению с вызовом ее в отдельной строке).

Вот пример:

(function() {
    var x = 5 + 4;
    console.log(x);
})();

Причина того, что используются вызывающие себя анонимные функции, заключается в том, что они никогда не должны вызываться другим кодом, поскольку они "настраивают" код, который должен вызываться (наряду с предоставлением области видимости функциям и переменным).

Другими словами, они похожи на программы, которые "создают классы" в начале программы. После того, как они были созданы (автоматически), единственными доступными функциями являются те, которые возвращаются анонимной функцией. Однако все остальные " скрытые 'функции все еще там, наряду с любым состоянием (переменные, установленные во время создания области видимости).

Очень круто.

В синтаксисе ES6 (пишу для себя, поскольку я продолжаю заходить на эту страницу в поисках быстрого примера):

// simple
const simpleNumber = (() => {
  return true ? 1 : 2
})()

// with param
const isPositiveNumber = ((number) => {
  return number > 0 ? true : false
})(4)

Это более подробное объяснение того, почему вы бы это использовали:

"Основной причиной использования IIFE является обеспечение конфиденциальности данных. Поскольку переменные var в JavaScript ограничивают их содержащую функцию, любые переменные, объявленные в IIFE, не могут быть доступны из внешнего мира".

http://adripofjavascript.com/blog/drips/an-introduction-to-iffes-immediately-invoked-function-expressions.html

Обычно код JavaScript имеет глобальную область видимости в приложении. Когда мы объявляем глобальную переменную в ней, есть шанс использовать ту же самую дублирующую переменную в какой-то другой области разработки для какой-то другой цели. Из-за этого дублирования может произойти какая-то ошибка. Таким образом, мы можем избежать этих глобальных переменных, используя немедленно вызывающее выражение функции, это выражение является самоисполняющимся выражением. Когда мы сделаем наш код внутри этого выражения IIFE, глобальная переменная будет похожа на локальную область видимости и локальную переменную.

Два способа мы можем создать IIFE

(function () {
    "use strict";
    var app = angular.module("myModule", []);
}());

ИЛИ ЖЕ

(function () {
    "use strict";
    var app = angular.module("myModule", []);
})();

В приведенном выше фрагменте кода " var app " теперь является локальной переменной.

Обычно мы не вызываем функцию сразу после того, как напишем ее в программе. Проще говоря, когда вы вызываете функцию сразу после ее создания, она называется IIFE - причудливым именем.

Я думаю, что 2 набора скобок делают это немного запутанным, но я видел другое использование в примере googles, они использовали нечто подобное, я надеюсь, это поможет вам лучше понять:

var app = window.app || (window.app = {});
console.log(app);
console.log(window.app);

так что если windows.app не определяется, то window.app = {} немедленно выполняется, так window.app назначается с {} во время оценки состояния, поэтому результат app а также window.app теперь стать {}поэтому вывод на консоль:

Object {}
Object {}
Другие вопросы по тегам