En javascript, quand voudriez-vous utiliser ceci:
(function(){
//Bunch of code...
})();
sur ceci:
//Bunch of code...
En javascript, quand voudriez-vous utiliser ceci:
(function(){
//Bunch of code...
})();
sur ceci:
//Bunch of code...
Réponses:
C'est une question de portée variable. Les variables déclarées dans la fonction auto-exécutable sont, par défaut, uniquement disponibles pour coder dans la fonction auto-exécutable. Cela permet d'écrire du code sans se soucier de la façon dont les variables sont nommées dans d'autres blocs de code JavaScript.
Par exemple, comme mentionné dans un commentaire d' Alexandre :
(function() {
var foo = 3;
console.log(foo);
})();
console.log(foo);
Cela enregistrera d'abord 3
et ensuite lancera une erreur sur le suivant console.log
car foo
n'est pas défini.
var
, comme ceci: ...function(){ foo=3;}
? Cela définirait une variable globale, non?
function(){ var foo = 3; alert(foo); }; alert(foo);
donc je ne comprends toujours pas
Simpliste. Donc très normal, c'est presque réconfortant:
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
Cependant, que se passe-t-il si j'inclus une bibliothèque javascript très pratique dans ma page qui traduit les caractères avancés dans leurs représentations de niveau de base?
Attends quoi?
Je veux dire, si quelqu'un tape un caractère avec une sorte d'accent dessus, mais je veux seulement des caractères 'anglais' AZ dans mon programme? Eh bien ... les caractères espagnol «ñ» et français «é» peuvent être traduits en caractères de base «n» et «e».
Donc, quelqu'un de gentil a écrit un convertisseur de caractères complet que je peux inclure dans mon site ... Je l'inclus.
Un problème: il contient une fonction appelée 'nom' identique à ma fonction.
C'est ce qu'on appelle une collision. Nous avons deux fonctions déclarées dans la même portée avec le même nom. Nous voulons éviter cela.
Nous devons donc en quelque sorte étendre notre code.
La seule façon d'étendre le code en javascript est de l'envelopper dans une fonction:
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
Cela pourrait résoudre notre problème. Tout est désormais fermé et n'est accessible qu'à partir de nos accolades d'ouverture et de fermeture.
Nous avons une fonction dans une fonction ... ce qui est bizarre à regarder, mais totalement légal.
Un seul problème. Notre code ne fonctionne pas. Notre variable userName n'est jamais répercutée dans la console!
Nous pouvons résoudre ce problème en ajoutant un appel à notre fonction après notre bloc de code existant ...
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
main();
Ou avant!
main();
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
Une préoccupation secondaire: quelles sont les chances que le nom «principal» n'ait pas encore été utilisé? ... donc très, très mince.
Nous avons besoin de PLUS de portée. Et un moyen d'exécuter automatiquement notre fonction main ().
Nous arrivons maintenant aux fonctions d'auto-exécution (ou auto-exécutables, auto-exécutables, peu importe).
((){})();
La syntaxe est maladroite comme péché. Mais ça marche.
Lorsque vous enveloppez une définition de fonction entre parenthèses et incluez une liste de paramètres (un autre ensemble ou des parenthèses!), Elle agit comme un appel de fonction .
Regardons donc à nouveau notre code, avec une syntaxe auto-exécutable:
(function main() {
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
)();
Ainsi, dans la plupart des didacticiels que vous lisez, vous serez désormais bombardé par le terme «auto-exécution anonyme» ou quelque chose de similaire.
Après de nombreuses années de développement professionnel, je vous invite fortement à nommer chaque fonction que vous écrivez à des fins de débogage.
Quand quelque chose ne va pas (et ça arrivera), vous vérifierez la trace dans votre navigateur. Il est toujours plus facile d'affiner vos problèmes de code lorsque les entrées de la trace de pile ont des noms!
Énorme longue haleine et j'espère que ça aide!
:)
L'auto-invocation (également appelée auto-invocation) se produit lorsqu'une fonction s'exécute immédiatement après sa définition. Il s'agit d'un modèle de base et sert de base à de nombreux autres modèles de développement JavaScript.
J'en suis un grand fan :) car:
Énormément - (Pourquoi devriez-vous dire que c'est bon?)
Plus ici .
Espace de noms. Les étendues de JavaScript sont au niveau de la fonction.
Je ne peux pas croire qu'aucune des réponses ne mentionne des globaux implicites.
La (function(){})()
construction ne protège pas contre les globaux implicites, ce qui pour moi est la plus grande préoccupation, voir http://yuiblog.com/blog/2006/06/01/global-domination/
Fondamentalement, le bloc fonction garantit que tous les "variables globales" dépendantes que vous avez définies sont confinés à votre programme, il ne vous protège pas contre la définition de globaux implicites. JSHint ou similaire peut fournir des recommandations sur la façon de se défendre contre ce comportement.
La var App = {}
syntaxe plus concise offre un niveau de protection similaire et peut être encapsulée dans le bloc fonction sur les pages «publiques». (voir Ember.js ou SproutCore pour des exemples réels de bibliothèques qui utilisent cette construction)
En ce qui concerne les private
propriétés, elles sont en quelque sorte surévaluées, sauf si vous créez un cadre public ou une bibliothèque, mais si vous devez les implémenter, Douglas Crockford a de bonnes idées.
J'ai lu toutes les réponses, il manque quelque chose de très important ici , je vais BAISER. Il y a 2 raisons principales pour lesquelles j'ai besoin de fonctions anonymes auto-exécutables, ou mieux dit " expression de fonction immédiatement invoquée (IIFE) ":
Le premier a été très bien expliqué. Pour le second, veuillez étudier l'exemple suivant:
var MyClosureObject = (function (){
var MyName = 'Michael Jackson RIP';
return {
getMyName: function () { return MyName;},
setMyName: function (name) { MyName = name}
}
}());
Attention 1: Nous n'affectons pas de fonction à MyClosureObject
, plus encore le résultat de l'invocation de cette fonction . Soyez conscient de ()
la dernière ligne.
Attention 2: Ce que vous devez en plus savoir sur les fonctions en Javascript, c'est que les fonctions internes ont accès aux paramètres et variables des fonctions, elles sont définies à l'intérieur.
Essayons quelques expériences:
Je peux MyName
utiliser getMyName
et cela fonctionne:
console.log(MyClosureObject.getMyName());
// Michael Jackson RIP
L'approche ingénue suivante ne fonctionnerait pas:
console.log(MyClosureObject.MyName);
// undefined
Mais je peux définir un autre nom et obtenir le résultat attendu:
MyClosureObject.setMyName('George Michael RIP');
console.log(MyClosureObject.getMyName());
// George Michael RIP
Edit: dans l'exemple ci MyClosureObject
- dessus est conçu pour être utilisé sans le new
préfixe, par conséquent, il ne doit pas être mis en majuscule.
Existe-t-il un paramètre et le "Bunch of code" renvoie une fonction?
var a = function(x) { return function() { document.write(x); } }(something);
Fermeture. La valeur de something
est utilisée par la fonction affectée à a
. something
pourrait avoir une valeur variable (pour la boucle) et chaque fois que a a une nouvelle fonction.
var x = something;
dans la fonction extérieure àx
que comme paramètre: imo c'est plus lisible de cette façon ...
x
et dépendez directement de la portée lexicale, c'est-à-dire document.write(something)
...
Isolement de la portée, peut-être. Pour que les variables à l'intérieur de la déclaration de fonction ne polluent pas l'espace de noms externe.
Bien sûr, sur la moitié des implémentations JS, elles le seront de toute façon.
Voici un exemple solide de l'utilité d'une fonction anonyme auto-invoquante.
for( var i = 0; i < 10; i++ ) {
setTimeout(function(){
console.log(i)
})
}
Production: 10, 10, 10, 10, 10...
for( var i = 0; i < 10; i++ ) {
(function(num){
setTimeout(function(){
console.log(num)
})
})(i)
}
Production: 0, 1, 2, 3, 4...
let
au lieu du var
premier cas, ça ira.
Puisque les fonctions en Javascript sont un objet de première classe, en le définissant de cette façon, il définit effectivement une "classe" un peu comme C ++ ou C #.
Cette fonction peut définir des variables locales et contenir des fonctions. Les fonctions internes (effectivement les méthodes d'instance) auront accès aux variables locales (effectivement les variables d'instance), mais elles seront isolées du reste du script.
Fonction auto-invoquée en javascript:
Une expression auto-invoquante est invoquée (démarrée) automatiquement, sans être appelée. Une expression auto-invoquante est invoquée juste après sa création. Ceci est essentiellement utilisé pour éviter les conflits de nommage ainsi que pour réaliser l'encapsulation. Les variables ou objets déclarés ne sont pas accessibles en dehors de cette fonction. Pour éviter les problèmes de minimisation (filename.min), utilisez toujours une fonction auto-exécutée.
Les fonctions auto-exécutables sont utilisées pour gérer la portée d'une variable.
La portée d'une variable est la région de votre programme dans laquelle elle est définie.
Une variable globale a une portée globale; il est défini partout dans votre code JavaScript et est accessible de n'importe où dans le script, même dans vos fonctions. En revanche, les variables déclarées dans une fonction ne sont définies que dans le corps de la fonction. Ce sont des variables locales, ont une portée locale et ne sont accessibles que dans cette fonction. Les paramètres de fonction comptent également comme des variables locales et ne sont définis que dans le corps de la fonction.
Comme indiqué ci-dessous, vous pouvez accéder à la variable variable globale à l'intérieur de votre fonction et notez également que dans le corps d'une fonction, une variable locale a priorité sur une variable globale du même nom.
var globalvar = "globalvar"; // this var can be accessed anywhere within the script
function scope() {
alert(globalvar);
localvar = "localvar" //can only be accessed within the function scope
}
scope();
Donc, fondamentalement, une fonction auto-exécutable permet d'écrire du code sans se soucier de la façon dont les variables sont nommées dans d'autres blocs de code javascript.
(function(){
var foo = {
name: 'bob'
};
console.log(foo.name); // bob
})();
console.log(foo.name); // Reference error
En fait, la fonction ci-dessus sera traitée comme une expression de fonction sans nom.
L'objectif principal d'encapsuler une fonction avec des parenthèses fermées et ouvertes est d'éviter de polluer l'espace global.
Les variables et les fonctions à l'intérieur de l'expression de fonction sont devenues privées (c'est-à-dire) qu'elles ne seront pas disponibles en dehors de la fonction.
La réponse courte est: pour prévenir la pollution de portée mondiale (ou supérieure).
IIFE (Immediately Invoked Function Expressions) est la meilleure pratique pour écrire des scripts en tant que plug-ins, modules complémentaires, scripts utilisateur ou tout autre script qui devrait fonctionner avec les scripts d'autres personnes . Cela garantit que toute variable que vous définissez ne donne pas d'effets indésirables sur d'autres scripts.
C'est l'autre façon d'écrire l'expression IIFE. Personnellement, je préfère cette méthode suivante:
void function() {
console.log('boo!');
// expected output: "boo!"
}();
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void
D'après l'exemple ci-dessus, il est très clair que l'IIFE peut également affecter l'efficacité et les performances, car la fonction qui ne doit être exécutée qu'une seule fois sera exécutée une fois, puis transférée dans le vide pour de bon . Cela signifie que la déclaration de fonction ou de méthode ne reste pas en mémoire.
void
auparavant. Je l'aime.
Vous devez d'abord visiter MDN IIFE , Maintenant quelques points à ce sujet
Il semble que cette question ait été répondue toute prête, mais je posterai quand même mon entrée.
Je sais quand j'aime utiliser des fonctions auto-exécutables.
var myObject = {
childObject: new function(){
// bunch of code
},
objVar1: <value>,
objVar2: <value>
}
La fonction me permet d'utiliser du code supplémentaire pour définir les attributs et les propriétés childObjects pour un code plus propre, comme la définition de variables couramment utilisées ou l'exécution d'équations mathématiques; Oh! ou vérification d'erreur. au lieu d'être limité à la syntaxe d'instanciation d'objets imbriqués de ...
object: {
childObject: {
childObject: {<value>, <value>, <value>}
},
objVar1: <value>,
objVar2: <value>
}
Le codage en général a de nombreuses façons obscures de faire la même chose, ce qui vous fait vous demander: "Pourquoi s'embêter?" Mais de nouvelles situations continuent de surgir où vous ne pouvez plus compter uniquement sur les principaux de base / principaux.
Étant donné votre question simple: "En javascript, quand voudriez-vous utiliser ceci: ..."
J'aime les réponses de @ken_browning et @ sean_holding, mais voici un autre cas d'utilisation que je ne vois pas mentionné:
let red_tree = new Node(10);
(async function () {
for (let i = 0; i < 1000; i++) {
await red_tree.insert(i);
}
})();
console.log('----->red_tree.printInOrder():', red_tree.printInOrder());
où Node.insert est une action asynchrone.
Je ne peux pas simplement appeler wait sans le mot clé async lors de la déclaration de ma fonction, et je n'ai pas besoin d'une fonction nommée pour une utilisation ultérieure, mais je dois attendre cet appel d'insertion ou j'ai besoin d'autres fonctionnalités plus riches (qui sait?) .
IIRC il vous permet de créer des propriétés et des méthodes privées.