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

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

// 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');

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

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

Ответ 1

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

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

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

DEMO Страница: https://jsfiddle.net/e7ooeq6m/

Я обсуждал эту модель в этом посте:

jQuery и $ questions

РЕДАКТИРОВАТЬ:

Если вы посмотрите на спецификацию сценария 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 Script:

FunctionDeclaration: идентификатор функции (FormalParameterListopt) {FunctionBody}

FunctionExpression: функция Identifieropt (FormalParameterListopt) {FunctionBody}

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

Это означает, что верно следующее.

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.

Ответ 2

Он вызвал самозапускаемую функцию.

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

Ответ 3

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

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

Ex. 1:

var message = 'SO';

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

foo(message);

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

Ex. 2:

var message = 'SO';

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

(foo)(message);     // calls foo

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

Ex. 3.

var message = 'SO';

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

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

Ex. 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

Ответ 4

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

Как и любое другое значение 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 является функция, а не блок ({}).

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

Ответ 5

Как работает 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 работает.

Ответ 6

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

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

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

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

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

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

Ответ 7

Вкратце о предыдущих комментариях:

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

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

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

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

Существует хороший синтаксис функции JavaScript обсуждения SO.

Ответ 8

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

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"
};

Ответ 9

Существует еще одна функция JavaScript 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

Ответ 10

Мое понимание вопроса об ответе таково, что:

Как работает эта магия:

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

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

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

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

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

Ответ 11

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

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

(это единственное реальное использование void, afaik)

или

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

или

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

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

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

Ответ 12

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

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

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

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

См:

Ответ 13

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

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

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

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

foo ('Few');

Потому что foo = function (msg) {alert (msg);}, поэтому вы можете заменить foo следующим образом:

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

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

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

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

Ответ 14

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

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 также позволяют вызвать этот тип вызова функции, и я также считаю, что интерпретатор добавляет круглые скобки за кулисы так или иначе, что возвращает нас к "вызов функции - это не вызов функции без круглых скобок".

Ответ 15

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

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

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

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

Он будет работать.

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

Ответ 16

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

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

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

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

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

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

Подробнее см. JavaScript/Анонимные функции.

Ответ 17

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

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

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

    Функция flyToTheMoon() {alert ( "Zoom! Zoom! Zoom!" ); } flyToTheMoon(); Heres тот же пример, созданный как анонимный Функция:

    var flyToTheMoon = function() {alert ( "Zoom! Zoom! Zoom!" ); } flyToTheMoon();

    Подробнее читайте здесь:

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

Ответ 18

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;
}());

Ответ 19

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