Domanda

Stavo leggendo alcuni post sulle chiusure e l'ho visto ovunque, ma non c'è una spiegazione chiara su come funzioni - ogni volta mi è stato semplicemente detto di usarlo...:

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

Ok, vedo che creeremo una nuova funzione anonima e poi la eseguiremo.Quindi dopo questo semplice codice dovrebbe funzionare (e funziona):

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

La mia domanda è: che tipo di magia accade qui?Lo pensavo quando ho scritto:

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

quindi verrebbe creata una nuova funzione senza nome come la funzione ""(msg) ...

ma allora perché non funziona?

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

Perché deve essere sulla stessa linea?

Potresti indicarmi qualche post o darmi una spiegazione?

È stato utile?

Soluzione

Eliminare il punto e virgola dopo la definizione della funzione.

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

di cui sopra dovrebbe funzionare.

DEMO pagina: https://jsfiddle.net/e7ooeq6m/

Ho discusso questo tipo di modello in questo post:

jQuery e $ domande

Modifica

Se si guarda a specifica lo script ECMA , ci sono 3 modi si può definire una funzione. (Pagina 98, Sezione 13 Definizione della funzione)

1. Utilizzando costruttore Funzione

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

2. Utilizzando dichiarazione di funzione.

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

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

3. Espressione Funzione

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

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

Così si può chiedere, qual è la differenza tra la dichiarazione e di espressione?

Da specifica ECMA Script:

  

FunctionDeclaration:       Funzione Identifier (FormalParameterListopt) {FunctionBody   }

     

FunctionExpression:       funzionare Identifieropt (FormalParameterListopt) {FunctionBody   }

Se si nota, 'identificatore' opzionale per l'espressione di funzione. E quando non si danno un identificatore, si crea una funzione anonima. Ciò non significa che non è possibile specificare un identificatore.

Questo significa che segue è valido.

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

punto importante da notare è che si può usare 'mySum' solo all'interno del corpo della funzione mySum, non al di fuori. Vedi seguente esempio:

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

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

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

Demo Live

Confrontare questo a

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

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

 test1(); //alerts 'function'

Armati di questa conoscenza, cerchiamo di analizzare il codice.

Quando si dispone di codice come,

    function(msg) { alert(msg); }

È stato creato un espressione di una funzione. E si può eseguire questo espressione di una funzione avvolgendolo all'interno parentesi.

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

Altri suggerimenti

Si chiama una funzione di auto-richiamata.

Quello che state facendo quando si chiama (function(){}) sta tornando un oggetto funzione. Quando si aggiunge () ad esso, viene richiamato e viene eseguito nulla nel corpo. Il ; indica la fine dell'istruzione, è per questo che la seconda invocazione fallisce.

Una cosa che ho trovato confusione è che gli operatori "()" sono di raggruppamento.

Ecco la vostra funzione di base dichiarata.

Ex. 1:

var message = 'SO';

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

foo(message);

funzioni sono oggetti, e possono essere raggruppati. Quindi cerchiamo di buttare parentesi intorno alla funzione.

Ex. 2:

var message = 'SO';

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

(foo)(message);     // calls foo

Ora, invece di dichiarare e destra-away chiamare la stessa funzione, possiamo usare la sostituzione di base di dichiararla come lo chiamiamo noi.

Ex. 3.

var message = 'SO';

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

Infine, non abbiamo bisogno di che foo extra perché non stiamo utilizzando il nome di chiamarlo! Le funzioni possono essere anonimi.

Ex. 4.

var message = 'SO';

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

Per rispondere alla tua domanda, rimandano al Esempio 2. La prima riga dichiara una qualche funzione senza nome e gruppi, ma non la chiama. Le seconde linee gruppi una stringa. Entrambi non fanno nulla. (Primo esempio di Vincent.)

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

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

Ma

(foo)
(msg); //works

Una funzione anonima non è una funzione con il nome "". E 'semplicemente una funzione senza un nome.

Come qualsiasi altro valore in JavaScript, una funzione non ha bisogno di un nome da creare. Anche se è di gran lunga più utile in realtà associarlo a un nome, proprio come qualsiasi altro valore.

Ma come ogni altro valore, a volte desidera utilizzarlo senza legarsi ad un nome. Questo è il modello di auto-invocazione.

Ecco una funzione e un numero, non è vincolata, non fanno nulla e non possono mai essere utilizzati:

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

Quindi dobbiamo memorizzarle in una variabile per essere in grado di usarli, come qualsiasi altro valore:

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

È inoltre possibile utilizzare lo zucchero syntatic di impegnare la funzione a una variabile:

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

Ma se dar loro un nome non è necessaria e potrebbe portare ad una maggiore confusione e meno la leggibilità, si può solo usarli subito.

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

Ecco, la mia funzione e miei numeri non sono legati ad una variabile, ma possono ancora essere utilizzati.

Detto così, sembra che la funzione di auto-invocazione non hanno alcun valore reale. Ma devi tenere a mente che JavaScript delimitatore campo di applicazione è la funzione e non il blocco ({}).

Quindi, una funzione di auto-invocando in realtà ha lo stesso significato di un C ++, C # o il blocco di Java. Il che significa che variabile creata al suo interno non si "fuga" al di fuori del campo di applicazione. Questo è molto utile in JavaScript al fine di non inquinare l'ambito globale.

E 'solo come funziona JavaScript. È possibile dichiarare una funzione denominata:

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

E lo chiamano:

foo("Hi!");

In alternativa, è possibile dichiarare una funzione anonima:

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

E non chiamate che:

foo("Hi!");

In alternativa, si può semplicemente non associare la funzione di un nome:

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

Le funzioni possono anche restituire funzioni:

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

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

E 'da notare che tutte le variabili definite con "var" nel corpo del make_foo saranno chiusi da più di ogni funzione restituita da make_foo. Questa è una chiusura, e significa che la qualsiasi modifica apportata al valore di uno funzione sarà visibile da un altro.

Questo consente di incapsulare le informazioni, se si desidera:

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

var hello = make_greeter("Hello!");

hello();

E 'solo come quasi ogni linguaggio di programmazione Java, ma funziona.

Il codice si mostra,

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

costituito da due istruzioni . Il primo è un'espressione che produce un oggetto funzione (che verrà poi garbage collection poiché non viene salvato). Il secondo è un'espressione che produce una stringa. Per applicare la funzione alla stringa, vi sia bisogno di passare la stringa come argomento della funzione quando viene creato (che mostra anche sopra), oppure è necessario memorizzare effettivamente la funzione in una variabile, in modo da poter applicarlo in un secondo momento, a vostro piacimento. In questo modo:

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

Si noti che memorizzando una funzione anonima (una funzione lambda) in una variabile, il tuo sono effettivamente dandogli un nome. Quindi si potrebbe altrettanto bene definire una funzione normale:

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

In sintesi dei commenti precedenti:

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

quando non assegnato a una variabile, produce un errore di sintassi. Il codice viene analizzata come un'istruzione di funzione (o definizione), che rende le parentesi chiusura sintatticamente corretto. L'aggiunta di parentesi intorno alla porzione funzione indica l'interprete (e programmatore) che si tratta di un'espressione di funzione (o invocazione), come in

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

Questa è una funzione di auto-invocazione, il che significa che si crea in forma anonima e viene eseguito immediatamente, perché l'invocazione avviene nella stessa linea in cui è dichiarata. Questa funzione di auto-invocazione è indicato con la sintassi familiare per chiamare una funzione senza argomenti, più ha aggiunto tra parentesi il nome della funzione:. (myFunction)();

una buona discussione SO JavaScript sintassi della funzione .

Questa risposta non è strettamente legato alla domanda, ma si potrebbe essere interessati a scoprire che questo tipo di caratteristica sintassi non è particolare alle funzioni. Per esempio, possiamo sempre fare qualcosa di simile:

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

relativi alle funzioni. Dal momento che sono oggetti che ereditano da Function.prototype, siamo in grado di fare cose come:

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

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

bar(); // alerts foo

E si sa, che non hanno nemmeno bisogno di circondare funzioni con parentesi al fine di eseguirli. In ogni caso, fino a quando si cerca di assegnare il risultato a una variabile.

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

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

Un altra cosa si può fare con le funzioni, non appena li si dichiara, è quello di richiamare l'operatore new su di loro e ottenere un oggetto. I seguenti sono equivalenti:

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

var obj = {
    foo : "bar"
};

C'è una proprietà più JavaScript funzione ha. Se si desidera chiamare stessa funzione anonima in modo ricorsivo.

(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

La mia comprensione della domanda del richiedente è tale che:

Come funziona la magia:

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

I può essere sbagliato. Tuttavia, la pratica usuale che le persone hanno familiarità con è:

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

Il motivo è tale che JavaScript parentesi AKA (), non può contenere dichiarazioni e quando il parser incontra la parola chiave function, sa analizzare come un'espressione di funzione e non una dichiarazione di funzione.

Fonte: post sul blog espressione di una funzione immediatamente Invocato-( IIFE)

esempi senza parentesi:

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

(questo è l'unico reale utilizzo del vuoto, per quanto ne so)

o

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

o

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

lavoro pure. la void causa l'espressione da valutare, nonché l'assegnazione e la scoppio. l'ultima opera con ~, +, -, delete, typeof, alcuni degli operatori unari (void è uno pure). non funzionante sono di couse ++, -- causa della necessità di una variabile.

l'interruzione di riga non è necessaria.

Si tratta di una funzione anonima self-executing. La prima serie di parentesi contengono le espressioni da eseguire, e la seconda serie di parentesi esegue quelle espressioni.

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

Peter Michaux discute la differenza di una coppia importante di parentesi .

Si tratta di un costrutto utile quando si cerca di nascondere le variabili dal namespace genitore. Tutto il codice all'interno della funzione è contenuta nell'ambito privato della funzione, che significa che non è possibile accedere a tutti da fuori della funzione, il che rende veramente privato.

See:

  1. chiusura (informatica)
  2. JavaScript namespacing
  3. Coppia Importante di Javascript parentesi

Un altro punto di vista

Innanzitutto, puoi dichiarare una funzione anonima:

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

Quindi lo chiami:

foo ('Few');

Perché foo = funzione(msg){avviso(msg);} quindi puoi sostituire pippo COME:

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

Ma dovresti racchiudere l'intera funzione anonima all'interno di una coppia di parentesi graffe per evitare errori di sintassi nella dichiarazione della funzione durante l'analisi.Poi abbiamo,

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

In questo modo è facile capirlo per me.

Quando hai fatto:

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

Hai terminato la funzione prima ('SO') a causa del punto e virgola. Se basta scrivere:

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

Si lavorerà.

Esempio di applicazione: http://jsfiddle.net/oliverni/dbVjg/

La semplice ragione per cui non funziona, non è a causa della ; che indica la fine della funzione anonima. È perché senza il () sull'estremità di una chiamata di funzione, non è una chiamata di funzione. Cioè,

function help() {return true;}

Se si chiama result = help(); questa è una chiamata a una funzione e restituirà true.

Se si chiama result = help; questa non è una chiamata. Si tratta di un incarico in cui l'aiuto è trattato come i dati da assegnare al risultato.

Quello che hai fatto è stato dichiarato / istanziare una funzione anonima con l'aggiunta del punto e virgola,

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

e poi ha cercato di chiamarlo in un altro comunicato utilizzando solo parentesi ... Ovviamente perché la funzione non ha nome, ma questo non funziona:

('SO');

L'interprete vede le parentesi sulla seconda linea, come una nuova istruzione / dichiarazione, e quindi non funziona, anche se avete fatto in questo modo:

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

E 'ancora non funziona, ma funziona quando si rimuove il punto e virgola perché l'interprete ignora gli spazi bianchi e carrozze e vede il codice completo come una dichiarazione.

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

Conclusione: una chiamata di funzione non è una chiamata di funzione senza l'() sull'estremità meno in condizioni specifiche come essere invocata da un'altra funzione, cioè, onload = 'aiuto' sarebbe eseguire la funzione di guida anche se le parentesi non erano incluso. Credo setTimeout e setInterval permettono anche questo tipo di chiamata di funzione troppo, e credo anche che l'interprete aggiunge le parentesi dietro le quinte in ogni caso che ci riporta a "una chiamata di funzione non è una chiamata di funzione senza le parentesi".

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

Questo è un metodo comune di utilizzare una funzione anonima come una chiusura, che molti usano framework JavaScript.

Questa funzione chiamata viene automaticamente quando il codice viene compilato.

Se si colloca ; alla prima linea, il compilatore trattata come due linee differenti. Quindi non è possibile ottenere gli stessi risultati di cui sopra.

Questo può anche essere scritta come:

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

Per ulteriori informazioni, guardare in funzioni JavaScript / anonimi .

  1. funzioni anonime sono funzioni che vengono dichiarati in modo dinamico a runtime. Si chiamano funzioni anonime perché non sono dato un nome nello stesso modo in cui le normali funzioni.

    funzioni anonime vengono dichiarate utilizzando l'operatore di funzione invece della dichiarazione di funzione. È possibile utilizzare l'operatore funzione per creare una nuova funzione, ovunque è valido per porre espressione. Per esempio si potrebbe dichiarare una nuova funzione come parametro per un funzione chiamata o per assegnare una proprietà di un altro oggetto.

    Ecco un tipico esempio di una funzione denominata:

    funzione flyToTheMoon () {alert ( "Zoom Zoom Zoom!!!"); } flyToTheMoon (); Ecco lo stesso esempio creata come un anonimo Funzione:

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

    Per i dettagli si prega di leggere qui:

    http://helephant.com/2008/08/23/javascript -Anonimo-funzioni /

L'IIFE compartimentalizza semplicemente la funzione e nasconde la variabile msg in modo da non "inquinare" il namespace globale. In realtà, basta fare cose semplici e fare come di seguito a meno che non si sta costruendo un sito web di miliardi di dollari.

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

Si potrebbe namespace vostra proprietà msg utilizzando un Rivelando modulo modello come:

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

funzioni anonime sono destinate ad essere one-shot accordo in cui si definisce una funzione al volo in modo da generare un output da voi da un ingresso che si sta fornendo. Tranne che non ha fornito l'input. Invece, hai scritto qualcosa sulla seconda linea ( 'COSI'); - una dichiarazione indipendente che non ha nulla a che fare con la funzione. Cosa ti aspettavi? :)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top