Pourquoi les résultats varient-ils en fonction du placement des accolades?

119

Pourquoi les extraits de code ci-dessous, tirés de cet article , produisent-ils des résultats différents en raison d'un seul changement dans le placement des accolades?

Lorsque l'accolade ouvrante {est sur une nouvelle ligne, test()retourne undefinedet "non - il s'est cassé: indéfini" s'affiche dans l'alerte.

function test()
{
  return
  { /* <--- curly brace on new line */
    javascript: "fantastic"
  };
}

var r = test();
try {
  alert(r.javascript); // does this work...?
} catch (e) {
  alert('no - it broke: ' + typeof r);
}

Lorsque l'accolade est sur la même ligne que return, test()renvoie un objet et "fantastique" est alerté.

function test()
{
  return { /* <---- curly brace on same line */
    javascript: "fantastic"
  };
}

var r = test();
try {
  alert(r.javascript); // does this work...?
} catch (e) {
  alert('no - it broke: ' + typeof r);
}

JustLearn
la source
la sémantique de semi-insertion après returnest légèrement différente de celle des autres endroits, et un saut de ligne "signifie plus" à cet endroit qu'il ne le ferait "à mi-chemin".
dandavis

Réponses:

165

C'est l'un des pièges de JavaScript: l'insertion automatique de points-virgules. Les lignes qui ne se terminent pas par un point-virgule, mais qui pourraient être la fin d'une instruction, sont automatiquement terminées, donc votre premier exemple ressemble effectivement à ceci:

function test()
{
  return; // <- notice the inserted semicolon
  { 
    javascript: "fantastic"
  };
}

Voir aussi le guide de style JS de Douglas Crockford , qui mentionne l'insertion de points-virgules.

Dans votre deuxième exemple, vous retournez un objet (construit par les accolades) avec la propriété javascriptet sa valeur de "fantastic", effectivement les mêmes que ceci:

function test() {
    var myObject = new Object();
    myObject.javascript = "fantastic";
    return myObject;
}
Résidu
la source
5
Fait amusant: sur certains moteurs, vous pouvez commenter les points-virgules insérés automatiquement
Christopher Tarquini
1
@ChrisT: Quoi? Lesquels? Est-ce exploré quelque part?
Sean McMillan
1
@SeanMcMillan J'ai certainement lu des articles à ce sujet, mais je n'arrive pas à en trouver un à partir d'une recherche rapide. Je me souviens que mettre return /*puis */{ commenter efficacement le point-virgule caché dans les anciennes versions de chrome. Je ne sais pas si cela s'applique toujours
Christopher Tarquini
2
A cause de ces bizarreries, je me suis fait une promesse il y a 10 ans: éloignez-vous du web! J'ai prié pour que les Interwebs disparaissent ... Malheureusement, cela ne s'est pas déroulé comme prévu, et maintenant je dois aussi lutter avec ces problèmes. Karma is ab * tch :)
Jowen
1
J'ai vu des gens qui sont religieusement opposés aux points-virgules en JavaScript, je me suis toujours demandé ce qu'ils faisaient de ce temps supplémentaire qu'ils gagnaient en ne mettant pas de points-virgules.
Iman Mohamadi
9

Javascript ne nécessite pas de points-virgules à la fin des instructions, mais l'inconvénient est qu'il doit deviner où se trouvent les points-virgules. La plupart du temps, ce n'est pas un problème, mais parfois il invente un point-virgule là où vous n'en aviez pas l'intention.

Un exemple de mon article de blog à ce sujet ( Javascript - presque pas basé sur une ligne ):

Si vous formatez le code comme ceci:

function getAnswer() {
   var answer = 42;
   return
      answer;
}

Ensuite, il est interprété comme ceci:

function getAnswer() {
  var answer = 42;
  return;
  answer;
}

L'instruction return prend sa forme sans paramètre et l'argument devient une instruction à part entière.

La même chose arrive à votre code. La fonction est interprétée comme:

function test()
{
  return;
  {
    javascript : "fantastic"
  };
}
Guffa
la source
3

Personnellement, je préfère le style Allman pour la lisibilité (par rapport au style K&R).

Au lieu de…

function test() {
  return {
    javascript : "fantastic"
  };
}

J'aime…

function test() 
{
  var obj =
  {
    javascript : "fantastic"
  };

  return obj;
}

Mais c'est une solution. Mais je peux vivre avec.

Michael R
la source
3
Je pense que nous devrions éviter les préférences personnelles qui s'écartent du courant dominant. Nous devrions suivre les choix de la majorité, ce qui favorise la cohérence, ce qui augmentera la lisibilité
Jowen
1
Je trouve son code plus lisible que le K&R. Assez subjectif quand vous voulez dire «lisible»
Bran
Je préfère aussi l'Allman ... mais à cause d'ASI, quand j'ai besoin de retourner un objet, je laisse le semi sur la même ligne que le retour. Je préfère cela plutôt que d'ajouter une ligne "var x =" ...
Mik
1

C'est parce que javascript met le plus souvent ";" à la fin de chaque ligne, donc fondamentalement, quand vous avez return {dans la même ligne, le moteur javascript voit qu'il y aura quelque chose de plus, et quand il est dans une nouvelle ligne, il pense que vous avez oublié de mettre ";", et le met pour vous.

cichy
la source
1
Je ne comprends pas pourquoi les réponses de Cichy, Darin et Ivo ont été rejetées?
BoltClock
1

Les accolades indiquent ici la construction d'un nouvel objet. Ainsi votre code équivaut à:

function test() {
  var a = { javascript : "fantastic" };
  return a;
}

ce qui fonctionne alors que si vous écrivez:

function test() {
  var a = { javascript : "fantastic" };
  return; // ; is automatically inserted 
      a;
}

ça ne marche plus.

Darin Dimitrov
la source
0

Le problème est en effet l'injection de point-virgule comme décrit ci-dessus. Je viens de lire un bon article de blog sur ce sujet. Il explique ce problème et bien plus encore sur javascript. Il contient également de bonnes références. Vous pouvez le lire ici

Ivo van der Wijk
la source
Oui, j'ai aussi lu cela, après avoir lu, je demande ici de mieux expliquer par le cerveau de js.
JustLearn