Зачем вам нужно вызывать анонимную функцию в той же строке?

StackOverflow https://stackoverflow.com/questions/1140089

Вопрос

Я читал несколько постов о закрытиях и видел это повсюду, но нет четкого объяснения, как это работает - каждый раз мне просто говорили использовать это...:

// Create a new anonymous function, to use as a wrapper
(function(){
    // The variable that would, normally, be global
    var msg = "Thanks for visiting!";

    // Binding a new function to a global object
    window.onunload = function(){
        // Which uses the 'hidden' variable
        alert( msg );
    };
// Close off the anonymous function and execute it
})();

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

(function (msg){alert(msg)})('SO');

Мой вопрос в том, что за волшебство здесь происходит?Я думал об этом, когда писал:

(function (msg){alert(msg)})

затем будет создана новая неназванная функция , подобная функции ""(msg) ...

но тогда почему это не работает?

(function (msg){alert(msg)});
('SO');

Почему это должно быть в одной строке?

Не могли бы вы, пожалуйста, указать мне на несколько сообщений или дать объяснение?

Это было полезно?

Решение

Опустите точку с запятой после определения функции.

(function (msg){alert(msg)})
('SO');

Вышесказанное должно сработать.

ДЕМОНСТРАЦИОННАЯ Страница: https://jsfiddle.net/e7ooeq6m/

Я обсуждал такого рода закономерности в этом посте:

jQuery и $ вопросы

Редактировать:

Если вы посмотрите на Спецификация скрипта ECMA, Существует 3 способа определения функции.(Страница 98, Раздел 13 Определение функции)

1.Использование конструктора функций

var sum = new Function('a','b', 'return a + b;');
alert(sum(10, 20)); //alerts 30

2.Использование объявления функции.

function sum(a, b)
{
    return a + b;
}

alert(sum(10, 10)); //Alerts 20;

3.Функциональное выражение

var sum = function(a, b) { return a + b; }

alert(sum(5, 5)); // alerts 10

Итак, вы можете спросить, в чем разница между объявлением и выражением?

Из спецификации скрипта ECMA:

Функциональное объявление :идентификатор функции ( FormalParameterListopt ){ FunctionBody }

Функциональное выражение :функция Identifieropt ( FormalParameterListopt ){ Функциональное тело }

Если вы заметили, "идентификатор" - это необязательно для выражения функции.И когда вы не указываете идентификатор, вы создаете анонимную функцию.Это не означает, что вы не можете указать идентификатор.

Это означает, что следующее является действительным.

var sum = function mySum(a, b) { return a + b; }

Важно отметить, что вы можете использовать 'mySum' только внутри тела функции mySum, а не снаружи.Смотрите следующий пример:

var test1 = function test2() { alert(typeof test2); }

alert(typeof(test2)); //alerts 'undefined', surprise! 

test1(); //alerts 'function' because test2 is a function.

Живая Демо-версия

Сравните это с

 function test1() { alert(typeof test1) };

 alert(typeof test1); //alerts 'function'

 test1(); //alerts 'function'

Вооружившись этими знаниями, давайте попробуем проанализировать ваш код.

Когда у вас есть код, подобный,

    function(msg) { alert(msg); }

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

    (function(msg) { alert(msg); })('SO'); //alerts SO.

Другие советы

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

Что вы делаете, когда звоните (function(){}) возвращает объект функции.Когда вы добавляете () для него вызывается и выполняется все, что находится в теле.Тот самый ; обозначает конец инструкции, вот почему 2-й вызов завершается неудачей.

Одна вещь, которая меня смущает, это то, что «()» — это группирующие операторы.

Вот ваша основная объявленная функция.

Бывший.1:

var message = 'SO';

function foo(msg) {
    alert(msg);
}

foo(message);

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

Бывший.2:

var message = 'SO';

function foo(msg) {  //declares foo
    alert(msg);
}

(foo)(message);     // calls foo

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

Бывший.3.

var message = 'SO';

(function foo(msg) {
    alert(msg);
})(message);          // declares & calls foo

Наконец, нам не нужен этот дополнительный foo, потому что мы не используем имя для его вызова!Функции могут быть анонимными.

Бывший.4.

var message = 'SO';

(function (msg) {   // remove unnecessary reference to foo
    alert(msg);
})(message);

Чтобы ответить на ваш вопрос, вернитесь к примеру 2.Ваша первая строка объявляет некую безымянную функцию и группирует ее, но не вызывает.Вторая строка группирует строку.Оба ничего не делают.(Первый пример Винсента.)

(function (msg){alert(msg)});  
('SO');                       // nothing.

(foo); 
(msg); //Still nothing.

Но

(foo)
(msg); //works

Анонимная функция не является функцией с именем "".Это просто функция без имени.

Как и любое другое значение в JavaScript, для создания функции не требуется имя.Хотя гораздо полезнее привязать его к имени, как и любое другое значение.

Но, как и любое другое значение, иногда вам нужно использовать его, не привязывая его к имени.Это шаблон самовызова.

Вот функция и число не связаны, они ничего не делают и никогда не могут быть использованы:

function(){ alert("plop"); }
2;

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

var f = function(){ alert("plop"); }
var n = 2;

Вы также можете использовать синтатический сахар для привязки функции к переменной:

function f(){ alert("plop"); }
var n = 2;

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

(function(){ alert("plop"); })(); // will display "plop"
alert(2 + 3); // will display 5

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

Сказав это, похоже, что самовызывающая функция не имеет реальной ценности.Но вы должны иметь в виду, что разделитель области JavaScript — это функция, а не блок ({}).

Таким образом, самовызывающая функция на самом деле имеет то же значение, что и блок C++, C# или Java.Это означает, что переменная, созданная внутри, не будет «утекать» за пределы области видимости.Это очень полезно в JavaScript, чтобы не загрязнять глобальную область видимости.

Именно так работает JavaScript.Вы можете объявить именованную функцию:

function foo(msg){
   alert(msg);
}

И назовите это:

foo("Hi!");

Или вы можете объявить анонимную функцию:

var foo = function (msg) {
    alert(msg);
}

И назовите это:

foo("Hi!");

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

(function(msg){
   alert(msg);
 })("Hi!");

Функции также могут возвращать функции:

function make_foo() {
    return function(msg){ alert(msg) };
}

(make_foo())("Hi!");

Ничего не стоит, если любые переменные, определенные с помощью «var» в теле make_foo будет закрыто каждой функцией, возвращаемой make_foo.Это замыкание, и это означает, что любое изменение значения, внесенное в значение одной функцией, будет видно другой.

Это позволяет вам инкапсулировать информацию, если вы хотите:

function make_greeter(msg){
    return function() { alert(msg) };
}

var hello = make_greeter("Hello!");

hello();

Именно так работает почти каждый язык программирования, кроме Java.

Код, который вы показываете,

(function (msg){alert(msg)});
('SO');

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

var f = (function (msg){alert(msg)});
f('SO');

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

function f(msg) {alert(msg)};
f('SO');

Подводя итог предыдущим комментариям:

function() {
  alert("hello");
}();

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

(function() {
  alert("hello");
})();

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

Есть хорошее обсуждение синтаксиса функции JavaScript SO.

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

alert(
    {foo: "I am foo", bar: "I am bar"}.foo
); // alerts "I am foo"

Относится к функциям.Поскольку это объекты, наследуемые от Function.prototype, мы можем делать такие вещи, как:

Function.prototype.foo = function () {
    return function () {
        alert("foo");
    };
};

var bar = (function () {}).foo();

bar(); // alerts foo

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

var x = function () {} (); // this function is executed but does nothing

function () {} (); // syntax error

Еще одна вещь, которую вы можете делать с функциями, как только вы их объявляете, — это вызывать метод new оператор над ними и получить объект.Следующие действия эквивалентны:

var obj = new function () {
    this.foo = "bar";
};

var obj = {
    foo : "bar"
};

Есть еще одно свойство функции JavaScript.Если вы хотите рекурсивно вызывать одну и ту же анонимную функцию.

(function forInternalOnly(){

  //you can use forInternalOnly to call this anonymous function
  /// forInternalOnly can be used inside function only, like
  var result = forInternalOnly();
})();

//this will not work
forInternalOnly();// no such a method exist

Я так понимаю вопрос спрашивающего:

Как работает это волшебство:

(function(){}) ('input')   // Used in his example

Возможно, я ошибаюсь.Однако обычная практика, с которой люди знакомы, такова:

(function(){}('input') )

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

Источник:Сообщение блога Выражение немедленно вызываемой функции (IIFE)

примеры без скобок:

void function (msg) { alert(msg); }
('SO');

(это единственное реальное использование пустоты, афаик)

или

var a = function (msg) { alert(msg); }
('SO');

или

!function (msg) { alert(msg); }
('SO');

работать тоже.тот void вызывает вычисление выражения, а также присваивание и взрыв.последний работает с ~, +, -, delete, typeof, некоторые из унарных операторов (void тоже один из них).не работают, это понятно ++, -- из-за требования переменной.

разрыв строки не обязателен.

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

(function () {
    return ( 10 + 20 );
})();

Питер Мишо обсуждает разницу в Важная пара круглых скобок.

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

Видеть:

  1. Замыкание (информатика)
  2. Пространство имен JavaScript
  3. Важная пара круглых скобок Javascript

Другая точка зрения

Во-первых, вы можете объявить анонимную функцию:

var foo = function(msg){
 alert(msg);
}

Затем вы называете это:

foo ('Few');

Потому что foo = функция (сообщение) {предупреждение (сообщение);} так что вы можете заменить фу как:

function(msg){
 alert(msg);
} ('Few');

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

(function(msg){
 alert(msg);
}) ('Few');

Таким образом, мне это легко понять.

Когда вы это сделали:

(function (msg){alert(msg)});
('SO');

Вы завершили функцию раньше ('SO') из-за точки с запятой.Если вы просто напишете:

(function (msg){alert(msg)})
('SO');

Это будет работать.

Рабочий пример: http://jsfiddle.net/oliverni/dbVjg/

Простая причина, почему это не работает, заключается не в том, что ; указывающий на конец анонимной функции.Это потому, что без () в конце вызова функции это не вызов функции.То есть,

function help() {return true;}

Если вы позвоните result = help(); это вызов функции, который вернет true.

Если вы позвоните result = help; это не звонок.Это задание, в котором помощь рассматривается как данные, которые необходимо присвоить результату.

Вы объявили/создали экземпляр анонимной функции, добавив точку с запятой,

(function (msg) { /* Code here */ });

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

('SO');

Интерпретатор воспринимает скобки во второй строке как новую инструкцию/оператор и поэтому не работает, даже если вы сделали это так:

(function (msg){/*code here*/});('SO');

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

(function (msg){/*code here*/})        // This space is ignored by the interpreter
('SO');

Заключение:вызов функции не является вызовом функции без () в конце, если только при определенных условиях, таких как вызов другой функции, то есть onload='help' будет выполняться функция справки, даже если круглые скобки не были включены.Я считаю, что setTimeout и setInterval также допускают этот тип вызова функции, и я также считаю, что интерпретатор все равно добавляет круглые скобки за кулисами, что возвращает нас к тому, что «вызов функции не является вызовом функции без скобок».

(function (msg){alert(msg)})
('SO');

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

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

Если разместить ; первую строку компилятор воспринимал как две разные строки.Таким образом, вы не можете получить те же результаты, что и выше.

Это также можно записать как:

(function (msg){alert(msg)}('SO'));

Для более подробной информации ознакомьтесь JavaScript/анонимные функции.

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

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

    Вот типичный пример именованной функции:

    функция flyToTheMoon() { оповещение("Увеличить!Увеличь!Увеличь!");} Мухомор ();Вот тот же пример, созданный как анонимная функция:

    var flyToTheMoon = функция() { оповещение("Увеличить!Увеличь!Увеличь!");} Мухомор ();

    Для получения подробной информации, пожалуйста, прочтите здесь:

    http://helephant.com/2008/08/23/javascript-anonymous-functions/

IIFE просто разделяет функцию на отдельные части и скрывает msg переменная, чтобы не «загрязнять» глобальное пространство имен.На самом деле, просто будьте проще и делайте, как показано ниже, если только вы не создаете веб-сайт стоимостью в миллиард долларов.

var msg = "later dude";
window.onunload = function(msg){
  alert( msg );
};

Вы можете использовать пространство имен msg имущество с использованием Выявление шаблона модуля нравиться:

var myScript = (function() {
    var pub = {};
    //myscript.msg
    pub.msg = "later dude";
    window.onunload = function(msg) {
        alert(msg);
    };
    //API
    return pub;
}());

Анонимные функции предназначены для одноразового действия, при котором вы определяете функцию на лету, чтобы она генерировала выходные данные из предоставленных вами входных данных.За исключением того, что вы не предоставили данные.Вместо этого вы написали что-то во второй строке («SO»);— независимое утверждение, не имеющее ничего общего с функцией.Чего ты ожидал?:)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top