Question

J'ai lu quelques posts sur les fermetures et les a vu partout, mais il n'y a pas d'explication claire comment cela fonctionne - chaque fois que je a juste dit à l'utiliser...:

// 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, je vois que nous allons créer de nouvelles fonction anonyme, et puis l'exécuter.Alors, après que ce simple code devrait fonctionner (et il le fait):

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

Ma question est quelle sorte de magie qui se passe ici?Je pensais que lorsque j'ai écrit:

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

puis une nouvelle fonction sans nom serait créé comme la fonction ""(msg) ...

mais alors pourquoi ne pas ce travail?

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

Pourquoi a-t-il besoin d'être dans la même ligne?

Pourriez-vous svp m'indiquer certains postes ou me donner une explication?

Était-ce utile?

La solution

Laissez tomber le point-virgule après la définition de la fonction.

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

doit travailler dessus.

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

J'ai discuté ce genre de modèle dans ce message:

jQuery et des questions sur $

EDIT:

Si vous regardez spécification script ECMA , il y a 3 façons dont vous pouvez définir une fonction. (Page 98, Section 13 Fonction Définition)

1. En utilisant constructeur Function

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

2. En utilisant la déclaration de fonction.

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

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

3. Fonction Expression

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

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

Vous pouvez demander, quelle est la différence entre la déclaration et d'expression?

De la spécification ECMA Script:

  

FunctionDeclaration:       Identificateur de fonction (FormalParameterListopt) {FunctionBody   }

     

FunctionExpression:       fonctionner Identifieropt (FormalParameterListopt) {FunctionBody   }

Si vous remarquez, 'identifiant' est option pour l'expression de la fonction. Et quand vous ne donnez pas un identifiant, vous créez une fonction anonyme. Cela ne signifie pas que vous ne pouvez pas spécifier un identifiant.

Cela signifie qui suit est valide.

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

Point important à noter est que vous pouvez utiliser « mySum » seulement à l'intérieur du corps de la fonction mySum, pas à l'extérieur. Voir l'exemple suivant:

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

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

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

Démo en direct

Comparez cela à

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

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

 test1(); //alerts 'function'

Armés de cette connaissance, nous allons essayer d'analyser votre code.

Lorsque vous avez du code comme,

    function(msg) { alert(msg); }

Vous avez créé une expression de fonction. Et vous pouvez exécuter cette expression de fonction en l'enveloppant à l'intérieur entre parenthèses.

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

Autres conseils

Il appelle une fonction appelée auto.

Qu'est-ce que vous faites lorsque vous appelez (function(){}) retourne un objet de fonction. Lorsque vous ajoutez () à elle, elle est invoquée et quoi que ce soit dans le corps est exécuté. Le ; indique la fin de l'instruction, c'est pourquoi le 2ème appel échoue.

Une chose que je trouve déroutant est que les « () » sont des opérateurs de regroupement.

Voici votre fonction de base déclarée.

Ex. 1:

var message = 'SO';

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

foo(message);

Les fonctions sont des objets, et peuvent être regroupés. Donc, nous allons jeter parens autour de la fonction.

Ex. 2:

var message = 'SO';

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

(foo)(message);     // calls foo

Maintenant, au lieu de déclarer et droit de suite appeler la même fonction, on peut utiliser la substitution de base pour le déclarer comme nous l'appelons.

Ex. 3.

var message = 'SO';

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

Enfin, on n'a pas besoin de ce truc supplémentaire parce que nous ne sommes pas en utilisant le nom de l'appeler! Les fonctions peuvent être anonymes.

Ex. 4.

var message = 'SO';

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

Pour répondre à votre question, reportez-vous revenir à l'exemple 2. Votre première ligne déclare une fonction sans nom et des groupes, mais ne l'appelle pas. Les seconds groupes de lignes d'une chaîne. Les deux ne font rien. (Premier exemple de Vincent.)

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

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

(foo)
(msg); //works

Une fonction anonyme n'est pas une fonction avec le nom « ». Il est tout simplement une fonction sans nom.

Comme toute autre valeur en JavaScript, une fonction n'a pas besoin d'un nom à créer. Bien qu'il soit beaucoup plus utile de lier effectivement à un nom comme toute autre valeur.

Mais comme toute autre valeur, vous voulez parfois l'utiliser sans se lier à un nom. C'est le modèle d'auto-invocation.

Voici une fonction et un certain nombre, non lié, ils ne font rien et ne peuvent jamais être utilisés:

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

Nous devons donc les stocker dans une variable pour pouvoir les utiliser, comme toute autre valeur:

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

Vous pouvez également utiliser le sucre syntactique pour lier la fonction à une variable:

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

Mais si les nommant n'est pas nécessaire et conduirait à une plus grande confusion et moins la lisibilité, vous pouvez simplement les utiliser tout de suite.

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

Ici, ma fonction et mes numéros ne sont pas liés à une variable, mais ils peuvent encore être utilisés.

Dit comme cela, il semble que la fonction auto-Allégation ont pas de valeur réelle. Mais vous devez garder à l'esprit que delimiter champ JavaScript est la fonction et non le bloc ({}).

Ainsi, une fonction d'auto-invocation a fait la même signification que C ++, C # ou Java bloc. Ce qui signifie que la variable créée à l'intérieur ne sera pas « fuite » en dehors du champ d'application. Ceci est très utile en JavaScript afin de ne pas polluer la portée globale.

Il est juste comment fonctionne JavaScript. Vous pouvez déclarer une fonction nommée:

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

Et appeler:

foo("Hi!");

Ou, vous pouvez déclarer une fonction anonyme:

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

Et appeler:

foo("Hi!");

Ou, vous pouvez tout simplement jamais lier la fonction à un nom:

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

Les fonctions peuvent également retourner les fonctions:

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

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

Il ne vaut rien que toutes les variables définies par « var » dans le corps de make_foo seront fermés sur chaque fonction renvoyée par make_foo. Ceci est une fermeture, et cela signifie que la moindre modification apportée à la valeur d'une fonction sera visible par un autre.

Cela vous permet d'encapsuler l'information, si vous le désirez:

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

var hello = make_greeter("Hello!");

hello();

Il est à quel point presque tous les langages de programmation Java, mais fonctionne.

Le code que vous montrez,

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

deux déclarations . La première est une expression qui donne un objet de fonction (qui sera ensuite ordures collectées parce qu'il est pas enregistré). La seconde est une expression qui fournit une chaîne de caractères. Pour appliquer la fonction à la chaîne, soit vous devez passer la chaîne comme argument à la fonction lorsqu'elle est créée (qui aussi vous montrer ci-dessus), ou vous devez stocker effectivement la fonction dans une variable, de sorte que vous pouvez appliquer à un moment plus tard, à votre guise. Comme ceci:

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

Notez que en stockant une fonction anonyme (une fonction lambda) dans une variable, vous êtes donnant effectivement un nom. Par conséquent, vous pouvez aussi bien définir une fonction régulière:

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

En résumé des commentaires précédents:

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

non affecté à une variable, on obtient une erreur de syntaxe. Le code est analysé comme une instruction de fonction (ou définition), ce qui rend les parenthèses de fermeture syntaxiquement incorrect. Ajout de parenthèses autour de la partie de fonction indique à l'interpréteur (et programmeur) que ce soit une expression de fonction (ou invocation), comme dans

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

Ceci est une fonction d'auto-invocation, ce qui signifie qu'il est créé de façon anonyme et exécute immédiatement parce que l'invocation se produit dans la même ligne où elle est déclarée. Cette fonction d'auto-Allégation est indiquée avec la syntaxe familière d'appeler une fonction sans argument, plus ajouté entre parenthèses autour du nom de la fonction:. (myFunction)();

Il est une bonne discussion SO JavaScript syntaxe de la fonction .

Cette réponse n'est pas strictement liée à la question, mais vous pourriez être intéressé de savoir que ce type de fonctionnalité de syntaxe n'est pas particulière aux fonctions. Par exemple, on peut toujours faire quelque chose comme ceci:

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

liées aux fonctions. Comme ils sont des objets qui héritent de Function.prototype, nous pouvons faire des choses comme:

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

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

bar(); // alerts foo

Et vous savez, on n'a même pas d'entourer les fonctions avec les parenthèses afin de les exécuter. Quoi qu'il en soit, aussi longtemps que nous essayons d'affecter le résultat à une variable.

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

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

Une autre chose que vous pouvez faire avec des fonctions, dès que vous les déclarez, est d'invoquer l'opérateur new sur eux et obtenir un objet. Les éléments suivants sont équivalentes:

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

var obj = {
    foo : "bar"
};

Il y a une plus fonction JavaScript a la propriété. Si vous voulez appeler même fonction anonyme récursive.

(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

Ma compréhension de la personne de la question est telle que:

Comment est-ce de la magie de travail:

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

J'ai peut-être tort.Cependant, la pratique habituelle que les gens sont familiers avec est:

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

La raison en est tels que JavaScript parenthèses AKA (), ne peut pas contenir de déclarations et lorsque l'analyseur rencontre le mot-clé function, il sait analyser comme une expression de fonction et non pas une déclaration de fonction.

Source:post de blog Immédiatement appelée à la Fonction d'Expression (IIFE)

exemples sans parenthèses:

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

(ce qui est la seule utilisation réelle du vide, autant que je sache)

ou

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

ou

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

travail aussi bien. l'void est à l'origine de l'expression d'évaluer, ainsi que l'affectation et la détonation. le dernier travaille avec ~, +, -, delete, typeof, certains opérateurs unaires (void est un aussi). ne fonctionne pas sont de couse ++, -- en raison de l'exigence d'une variable.

le saut de ligne n'est pas nécessaire.

Il est une fonction anonyme auto-exécution. Le premier ensemble de supports contenant les expressions à exécuter, et le second ensemble de crochets exécute ces expressions.

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

Pierre Michaux traite de la différence dans Une importante paire de Parenthèses .

Il est une construction utile lorsque vous essayez de cacher les variables de l'espace de noms de parent. Tout le code de la fonction est contenue dans le champ privé de la fonction, ce qui signifie qu'il ne peut pas être accessible à tous à l'extérieur de la fonction, ce qui rend vraiment privé.

Voir:

  1. fermeture (de l'informatique)
  2. JavaScript Les espaces de noms
  3. Paire Important de Javascript de Parenthèses

Un autre point de vue

D'abord, vous pouvez déclarer une fonction anonyme:

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

Ensuite, vous l'appelez:

foo ('Few');

Comme foo = function (msg) {alert (msg);} de sorte que vous pouvez remplacer foo comme:

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

Mais vous devez envelopper toute votre fonction anonyme à l'intérieur deux accolades pour éviter les erreurs de syntaxe de déclarer la fonction lors de l'analyse. Ensuite, nous avons,

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

De cette manière, il est facile à comprendre pour moi.

La simple raison pour laquelle il ne fonctionne pas est pas à cause de la ; indiquant la fin de la fonction anonyme. Il est dû au fait sans () à la fin d'un appel de fonction, il est un appel de fonction. C'est,

function help() {return true;}

Si vous appelez ce result = help(); est un appel à une fonction et retourne vrai.

Si vous appelez result = help; ce n'est pas un appel. Il est une mission où l'aide est traité comme à affecter pour résultat des données.

Ce que vous avez été déclaré / instancier une fonction anonyme en ajoutant le point-virgule,

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

et puis essayé de l'appeler dans une autre déclaration en utilisant des parenthèses juste ... De toute évidence parce que la fonction n'a pas de nom, mais cela ne fonctionne pas:

('SO');

L'interprète voit les parenthèses sur la deuxième ligne comme une nouvelle instruction / déclaration, et donc il ne fonctionne pas, même si vous l'avez fait comme ceci:

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

Il ne fonctionne toujours pas, mais il fonctionne lorsque vous supprimez le point-virgule, car l'interprète ne tient pas compte des espaces blancs et des voitures et voit le code complet comme une instruction.

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

Conclusion: un appel de fonction n'est pas un appel de fonction sans () à la fin, à moins, dans des conditions spécifiques telles que invoquée par une autre fonction, qui est, onload = « help » exécuter la fonction d'aide, même si les parenthèses ne sont pas inclus. Je crois setTimeout et setInterval permettent également ce type d'appel de fonction aussi, et je crois aussi que l'interprète ajoute les parenthèses dans les coulisses de toute façon ce qui nous ramène à « un appel de fonction n'est pas un appel de fonction sans les parenthèses ».

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

Ceci est une méthode courante d'utiliser une fonction anonyme comme une fermeture qui utilisent de nombreux frameworks JavaScript.

Cette fonction est appelée automatiquement lorsque le code est compilé.

Si vous placez ; à la première ligne, le compilateur traité comme deux lignes différentes. Donc, vous ne pouvez pas obtenir les mêmes résultats que ci-dessus.

Cela peut aussi être écrit:

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

Pour plus de détails, regardez dans JavaScript / Fonctions anonymes .

  1. Les fonctions anonymes sont des fonctions qui sont dynamiquement déclarées à exécution. Ils sont appelés fonctions anonymes parce qu'ils ne sont pas étant donné un nom de la même manière que les fonctions normales.

    Les fonctions anonymes sont déclarées en utilisant l'opérateur de fonction à la place de la déclaration de fonction. Vous pouvez utiliser l'opérateur de fonction créer une nouvelle fonction où il est valable de mettre une expression. Pour exemple, vous pouvez déclarer une nouvelle fonction en tant que paramètre à un appel de fonction ou d'attribuer une propriété d'un autre objet.

    Voici un exemple typique d'une fonction nommée:

    Fonction flyToTheMoon () {alert ( "Zoom Zoom Zoom!!"); } Voler vers la lune(); Voici le même exemple créé comme un anonyme fonction:

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

    Pour plus de détails s'il vous plaît lire ici:

    http://helephant.com/2008/08/23/javascript -Anonyme-fonctions /

Le compartimente simplement Ia vie et la fonction cache la variable msg afin de ne pas « polluer » l'espace de noms global. En réalité, il suffit de garder simple et faire comme ci-dessous, sauf si vous construisez un site web milliards de dollars.

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

Vous pouvez namespace votre propriété msg en utilisant un Révéler Motif du module comme:

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

Les fonctions anonymes sont destinées à être one-shot deal où vous définissez une fonction à la volée afin qu'il génère une sortie de vous d'une entrée que vous fournissez. Sauf que vous n'avez pas fourni l'entrée. , Vous avez écrit quelque chose à la place sur la deuxième ligne ( « SO »); - une déclaration indépendante qui n'a rien à voir avec la fonction. Qu'est-ce que vous attendiez? :)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top