Une autre langue que JavaScript est-elle différente entre les points de départ des accolades (même ligne et ligne suivante)?

Aujourd’hui, alors que je lisais aléatoirement le livre des modèles JavaScript O’Reilly, j’ai trouvé une chose intéressante (page 27 pour référence).

Dans Javascript, dans certains cas, il y a une différence si l’emplacement de départ de l’accolade est différent.

function test_function1() { return { name: 'rajat' }; } var obj = test_function1(); alert(obj); //Shows "undefined" 

Tandis que

 function test_function2() { return { name: 'rajat' }; } var obj = test_function2(); alert(obj); //Shows object 

JSfiddle Demo

Est-ce qu’une autre langue a un tel comportement? Si oui, alors je devrais changer d’habitude à coup sûr. 🙂

Je suis principalement préoccupé par PHP, C, C ++, Java et Ruby.

Tout langage qui ne repose pas sur des points-virgules (mais sur des lignes nouvelles) pour délimiter des instructions le permet. Considérez Python :

 >>> def foo(): ... return ... { 1: 2 } ... >>> def bar(): ... return { 1: 2 } ... >>> foo() >>> bar() {1: 2} 

Vous pourriez être en mesure de construire un cas similaire en Visual Basic, mais je ne peux pas comprendre comment, car VB est assez ressortingctif en ce qui concerne les valeurs. Mais les éléments suivants devraient fonctionner, à moins que l’parsingur statique ne se plaint d’un code inaccessible:

 Try Throw New Exception() Catch ex As Exception Throw ex.GetBaseException() End Try ' versus Try Throw New Exception() Catch ex As Exception Throw ex.GetBaseException() End Try 

Parmi les langues que vous avez mentionnées, Ruby possède la même propriété. PHP, C, C ++ et Java ne se contentent pas de supprimer la nouvelle ligne en tant qu’espace et nécessitent des points virgules pour délimiter les instructions.

Voici le code équivalent de l’exemple Python en Ruby:

 >> def foo >> return { 1 => 2 } >> end => nil >> def bar >> return >> { 1 => 2 } >> end => nil >> foo => {1=>2} >> bar => nil 

L’interpréteur JavaScript ajoute automatiquement un ; à la fin de chaque ligne si elle n’en trouve pas (à quelques exceptions près, ne pas les entrer ici :).

Donc, fondamentalement, le problème n’est pas l’emplacement des accolades (qui représentent ici un littéral d’object, pas un bloc de code comme dans la plupart des langues), mais cette petite “fonctionnalité” qui oblige votre premier exemple à return ; => undefined Vous pouvez vérifier le comportement du return dans la spécification ES5 .

Pour les autres langages ayant un comportement similaire, consultez la réponse de Konrad .

Certainement. Le langage de programmation go de Google présente un comportement très similaire (avec toutefois des effets différents). Comme expliqué ici:

En fait, le langage formel utilise des points-virgules, un peu comme en C ou en Java, mais ils sont insérés automatiquement à la fin de chaque ligne qui ressemble à la fin d’une instruction. Vous n’avez pas besoin de les taper vous-même.

..couper…

Cette approche permet d’obtenir un code clair, sans virgule. La seule surprise est qu’il est important de mettre l’accolade d’ouverture d’une construction telle qu’une instruction if sur la même ligne que le if; si vous ne le faites pas, il existe des situations qui peuvent ne pas comstackr ou donner un résultat erroné. La langue force le style de corset dans une certaine mesure.

Secrètement, je pense que Rob Pike voulait juste une excuse pour exiger le style One True Brace.

La réponse à cette question est assez facile. Tout langage comportant une “insertion automatique de point-virgule” peut être en difficulté sur cette ligne. Le problème avec ceci

 return { name: 'rajat' }; 

..si le moteur js va insérer un point-virgule après le return; déclaration (et par conséquent, retourne undefined ). Cet exemple est une bonne raison pour ouvrir les accolades toujours à droite et jamais à gauche également. Puisque vous avez déjà remarqué correctement, s’il y a un crochet entre les deux lignes, l’interpréteur le remarquera et ne pourra pas insérer de point-virgule.

FWIW, JSLint rapporte plusieurs avertissements avec cette syntaxe:

 $ jslint -stdin function foo(){ return { x: "y" }; } ^D (3): lint warning: unexpected end of line; it is ambiguous whether these lines are part of the same statement return ........^ (3): lint warning: missing semicolon { x: "y" }; ..^ (3): lint warning: unreachable code { x: "y" }; ..^ (3): lint warning: meaningless block; curly braces have no impact { x: "y" }; ..^ (3): lint warning: use of label { x: "y" }; .....^ (3): lint warning: missing semicolon { x: "y" }; ...........^ (3): lint warning: empty statement or extra semicolon { x: "y" }; ............^ 0 error(s), 7 warning(s) 

La première langue dans laquelle je suis tombé sur cette question était awk (qui a également son lot de “bizarreries” de syntaxe; les semi-points optionnels, la concaténation de chaînes utilisant uniquement des espaces, etc.) Je pense que les concepteurs de DTrace sur awk, avait assez de sens pour ne pas copier ces fonctionnalités, mais je ne me souviens pas de ma tête. Un exemple simple (en comptant le nombre de tags ENTITY dans une DTD, à partir de mon Mac):

 $ cat printEntities.awk # This prints all lines where the ssortingng ENTITY occurs /ENTITY/ { print $0 } $ awk -f printEntities.awk < /usr/share/texinfo/texinfo.dtd | wc -l 119 

Si ce petit script était plutôt écrit avec l'accolade sur une ligne à part, voici ce qui arriverait:

 $ cat printAll.awk # Because of the brace placement, the print statement will be executed # for all lines in the input file # Lines containing the ssortingng ENTITY will be printed twice, # because print is the default action, if no other action is specified /ENTITY/ { print $0 } $ awk -f printAll.awk < /usr/share/texinfo/texinfo.dtd | wc -l 603 $ /bin/cat < /usr/share/texinfo/texinfo.dtd | wc -l 484 $