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


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

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

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

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

19 364

19 ответов:

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

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

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

демонстрационная страница:https://jsfiddle.net/e7ooeq6m/

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

jQuery и $ questions

EDIT:

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

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.

Live Demo

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

 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(){}) возвращает объект функции. Когда вы добавляете () к нему, он вызывается и что в теле выполняется. Элемент ; обозначает конец оператора, поэтому второй вызов не выполняется.

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

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

Ex. 1:

var message = 'SO';

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

foo(message);

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

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

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

как и любое другое значение в 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.

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

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

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

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 скобки АКА (), не может содержать операторы и когда синтаксический анализатор встречает ключевое слово функции, он знает, чтобы разобрать его как выражение функции, а не объявление функции.

Источник: Блог сразу-вызывается функция выражения (жизнь)

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

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

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

или

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

или

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

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

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

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

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

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

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

посмотреть:

  1. закрытие (информатика)
  2. Пространство Имен JavaScript
  3. важная пара скобок Javascript

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

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

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

тогда вы называете это:

foo ('Few');

, потому что foo = function (msg){alert (msg);} так что вы можете заменить фу как:

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 / Anonymous Функции.

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

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

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

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

    var flyToTheMoon = function () { alert ("Zoom! Зум! Зум!"); } 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'); - независимый оператор, который не имеет ничего общего с функцией. А чего ты ожидал? :)