2014-06-05 4 views
2

Airbnd suggests Je fais ceci:JavaScript Bang "!" Fonctions vs Semi-Colon "" IIFEs

!function() { 
    // ... 
}(); 

Parce que:

Cela garantit que si un module malformé oublie d'inclure un point-virgule finale il n'y a pas d'erreurs dans la production lorsque les scripts sont concaténés .

Le coup me permet de travailler autour des règles de grammaire de la langue:

// Evaluated in Chromium 34 console. 
function(){}(); // => SyntaxError: Unexpected token (
!function(){}(); // => true 

Et quand concaténer autres modules le bang semble faire l'affaire:

!function(){}();function(){}(); // => SyntaxError: Unexpected token (
!function(){}();!function(){}(); // => true 
(function(){}());!function(){}(); // => true 

Cependant, il ne semble en fait être "sûr", parce que si quelqu'un d'autre n'a pas de point-virgule à la fin de son script:

!function(){}()!function(){}(); // => SyntaxError: Unexpected token ! 
(function(){}())!function(){}(); // => SyntaxError: Unexpected token ! 

Il semblerait qu'un demi-colon IIFE est meilleur.

;(function() { 
    // ... 
}()); 

!function(){}();(function(){}()); // => undefined 
(function(){}());(function(){}()); // => undefined 
!function(){}();;(function(){}()); // => undefined 
(function(){}());;(function(){}()); // => undefined 

Quelque chose me manque? Est-il vraiment acceptable d'utiliser Bang?! " fonctions ou dirigent un point-virgule ";" Les IIFE sont-ils vraiment supérieurs en raison de leur concaténation?

Répondre

5

Vous avez toujours IEFEs là-bas. Si vous les enveloppez entre parenthèses ou préfixez-les avec un ! est votre choix, et ne fait pas de différence. Vous avez besoin de l'un ou de l'autre pour forcer la fonction à être analysée en tant qu'expression. Voir javascript function leading bang ! syntax pour plus de détails.

Que vous préfixe construire ensemble avec un ; pour éviter les erreurs de concaténation avec des scripts pauvres écrits (What does the leading semicolon in JavaScript libraries do?) est totalement indépendant .Vous pouvez mélanger les motifs que vous voulez:

!function(){…}() // not safe for arbitrary concatenation 
(function(){…}()) // not safe for arbitrary concatenation either 
;!function(){…}() 
;(function(){…}()) 

Cependant, il y a un cas de concaténation où () vs ! fait une différence: si deux scripts sont concaténés pour qu'il y ait une nouvelle ligne entre les deux, et l'ancien ne se termine pas par un point-virgule. Cela permet automatic semicolon insertion to jump in - lorsque la ligne suivante commence par un coup!

1 + 2    // script A 
!function(){…}(); // script B 
// works! 

1 + 2    // script A 
(function(){…}()); // script B 
// runtime error: "2 is not a function" (or whatever the previous line ends in) 

Nous apprenons: Terminez toujours votre script par un point-virgule. Utilisez une concaténation intelligente. Commencez votre script avec un point-virgule si vous avez besoin d'être en sécurité contre la concaténation stupide.

4

Le ! n'a rien à voir avec la protection contre les points-virgules manquants lors de la concaténation de fichiers. Il est souvent utilisé pour appliquer que la définition de fonction suivante est évaluée comme expression, pas comme déclaration. D'autre part, un point-virgule de premier plan met fin à toute déclaration d'expression "ouverte" qui pourrait lui être présentée.

Mais si vous suivez le explanation, il semble que ! suffirait si c'est le premier caractère de la ligne. Apparemment, JS ajouterait un point-virgule à la précédente en raison de ASI. Cependant, cela semble être une approche plus fragile, car il se peut que vous ne contrôliez pas totalement la concaténation des modules. L'utilisation d'un point-virgule est définitivement "plus sûre".

-2

En fait, cela fonctionne aussi:

;!function() { 
    // ... 
}(); 

!function(){}()!function(){}(); // => SyntaxError: Unexpected token ! 
!function(){}();!function(){}(); // => true 
(function(){}());!function(){}(); // => true 
!function(){}();;!function(){}(); // => true 
(function(){}());;!function(){}(); // => true 

Alors IIFEs ne sont pas mieux que les fonctions bang, comme je l'ai distraitement-supposais dans le dernier paragraphe de ma question. Peu importe si vous utilisez une fonction bang ou un IIFE, un point-virgule avant eux est une bonne technique défensive.

+0

Les IIFE sont "_no pas mieux que les fonctions bang ..." "Hein? IIFE et "fonctions _bang" ne sont pas vraiment liés. Les IIFE sont une construction qui empêche de polluer la portée globale. Vous pouvez placer un '!' Devant une déclaration de fonction pour le faire évaluer en tant qu'expression de fonction ... Aussi, qu'est-ce que le diable fait "_un point-virgule en tête est le dealbreaker_"? – jahroy

+0

1. Dans le dernier paragraphe de ma question, j'ai fait l'hypothèse erronée que l'on ne pouvait faire précéder un IIFE qu'avec un point-virgule. Cependant, j'ai réalisé par la suite que je pourrais tout aussi bien ajouter une fonction bang avec un. 2. Dans ce cas, une fonction bang OU un IIFE pourrait être utilisé pour définir un module. 3. Sans un point-virgule, vous obtiendrez une erreur de syntaxe. Je vais mettre à jour cet article pour clarifier cela. – Jackson