Pourquoi {} + {} n'est plus NaN dans la console Chrome?


144

J'ai remarqué aujourd'hui que Chrome 49 ne sort plus NaNlorsque vous tapez {}+{}dans la console. Au lieu de cela, il génère la chaîne [object Object][object Object].

Pourquoi est-ce? La langue a-t-elle changé?


13
ressemble à Chrome traite maintenant cette opération comme un concat de chaîne plutôt que comme une addition. POURQUOI c'est, je ne sais pas, c'est pourquoi c'est un commentaire pas une réponse :) essayez var e = {}; e.toString()et vous verrez ce que je veux dire
user428517

19
"La langue a-t-elle changé?" No.
Felix Kling

6
@FelixKling La langue va- t -elle changer? ...non. : c
chat

18
Peut-être que WATMAN a quelque chose à voir avec ça?
rickster

1
@rickster c'est comme ça que je l'ai trouvé. Je recréais cela pour une présentation.
Filip Haglund

Réponses:


152

Les outils de développement Chrome encapsulent désormais automatiquement tout ce qui commence par {et se termine par }une paire implicite de parenthèses ( voir le code ), pour forcer son évaluation en tant qu'expression. De cette façon, {}crée un objet vide maintenant. Vous pouvez le voir si vous revenez dans l'historique ( ), la ligne précédente sera contenue dans (…).

Pourquoi? Je ne sais pas, mais je pourrais supposer que cela réduit la confusion pour les débutants qui ne connaissent pas la chose bloc-vs-objet-littéral, et c'est aussi plus utile si vous voulez simplement évaluer une expression.

Et en fait, c'est le raisonnement, comme indiqué dans le bogue 499864 . Pratique pure. Et parce que le nœud REPL l'avait aussi ( voir code ).


182
Stupid Chrome, {a:1}),({b:2}devrait générer une erreur, pas produire un objet.
Oriol

29
C'est ce qui se passe lorsque vous analysez des structures imbriquées arbitrairement profondes avec regex stackoverflow.com/questions/1732348/…
Filip Haglund

4
Je ne sais pas pourquoi, mais d'une manière ou d'une autre, quand je vois mes messages là-bas, je me sens "célèbre" bien que cette page soit tout aussi publique que celle-ci: D Problème de StackOverflow bizarre. Voici ma réponse plus ancienne au problème stackoverflow.com/questions/17268468/…
Benjamin Gruenbaum

3
Je n'aime pas l'implémentation actuelle et je prévois de la réparer. bugs.chromium.org/p/chromium/issues/detail?id=499864#c17
Zirak

1
@Zirak Bonne chance pour réparer ces ordures, OMI, il devrait être annulé dès que possible. Mais si vous voulez l'améliorer, pensez à ajouter une nouvelle ligne avant l'insertion )au cas où elle serait dans un commentaire, par exemple {a:3} // :-}pourrait encore produire un objet.
Oriol

44

Si vous appuyez sur la flèche vers le haut après avoir vérifié cela, vous remarquerez qu'au lieu de {} + {}cela ({} + {}), elle s'affiche , ce qui entraîne "[object Object][object Object]".

En comparaison, dans Firefox, {} + {}s'affiche toujours NaN, mais si vous le faites, ({} + {})il s'affiche également "[object Object][object Object]".

Donc, il semble que Chrome ajoute automatiquement les parenthèses environnantes lorsqu'il voit cette opération.


22
cette réponse est correcte. mais wow, mec, je ne suis pas sûr que j'aime que le chrome fasse ça. mauvais google.
user428517

1
@sgroves Je serais intéressé de voir si c'est la même chose dans Canary, et si cela a été fait exprès ou s'il s'agit en fait d'un bug.
J. Titus

8
{} + {}lorsqu'il n'est pas "nettoyé" ({} + {})est traité comme + {}parce qu'il {}est analysé comme un bloc vide.
Gregory Nisbet

7
Pourquoi retournerait-il NaN en premier lieu?
0x499602D2

25
@ 0x499602D2: Parce qu'à moins que vous ne fassiez les parens (ou que vous ne fassiez passer l'analyseur à une expression plutôt qu'une instruction), l'initiale {}est juste un bloc de code vide et est ignoré, nous laissant avec +{}, qui est un objet unaire +et vide initialiseur. +contraindra son argument en nombre, ce qui implique la conversion de l'objet en primitive (qui finira par être un toStringdans ce cas, ce qui entraînera "[object Object]"), et ainsi nous obtenons +"[object Object]"ce qui est NaNparce "[object Object]"qu'il ne peut pas être converti en un nombre valide.
TJ Crowder

4

À partir de Chrome 54 en ce qui concerne la console:

📎- "J'ai converti ce bloc en objet pour vous" -Clippy Malheureusement, j'ai ajouté moi-même la citation de Clippy. La console ne donne aucune information sur ce qu'elle a fait pour vous.

Les nouvelles règles sont incroyablement simples, ce qui nous évite d'avoir à taper laborieusement ces 2 caractères difficiles o=ou 0,avant de coller des objets littéraux dans la console:

  • Si vous avez du code qui commence par: un espace facultatif, (aucun commentaire autorisé) suivi d'un {;
  • et ce code pourrait être interprété comme un objet;
  • et cet objet n'est suivi d'aucun autre code, sauf si:
  • le code après le premier objet est un opérateur binaire,
  • alors il peut y avoir autant d'opérations que vous le souhaitez, y compris des regroupements
  • à condition que l'opérateur final ait un littéral Object dans la position de droite;
  • et cet objet final n'a pas été groupé en parens
  • et ce code ne se termine pas par un point-virgule
  • et il n'y a aucun commentaire à la suite du code (les commentaires internes sont autorisés tant qu'ils ne sont pas en position initiale ou finale)
  • alors et alors seulement votre JavaScript (qui peut ou non être un code valide) sera réintégré en tant qu'objet valide. Vous ne serez pas informé que votre code a été réinterprété.

{wat:1}),({wat:2} Est enfin une erreur à nouveau.

{let i=0;var increment=_=>i++} est correctement autorisé, enfin, ce qui est une bonne façon de faire des fermetures.

Cependant, ce qui suit est incorrectement un objet, c'est juste pour la commodité comme mentionné par @Bergi, il interprète mal JS pour vous aider! La spécification dit que c'est un bloc avec une instruction étiquetée "foo" avec un littéral 1 qui n'est assigné à rien.

{foo:1}

Ce qui précède doit être le même que

if(1) {
    foo: 1
}

Ce qui suit est traité correctement comme un bloc ... car il a un commentaire devant lui!

//magic comment
{foo:1}

Alors est-ce:

{foo:1}
//also magic

Ceci est un objet:

{foo:
//not so magic comment
1}

C'est une erreur

//not so magic comment
{foo:1}.foo

Alors est-ce:

{foo:1}.foo

C'est bon:

1..wat

undefined

est donc ceci:

['foo'][0]

Le suivant est correctement interprété comme un objet enfoncé dans la position de l'expression avec un, 0,ce qui est généralement la façon dont nous nous assurons sans ambiguïté d'avoir une expression au lieu d'une instruction.

0,{foo:1}.foo

Je ne comprends pas pourquoi ils enveloppent la valeur dans des parenthèses. JS a des décisions de conception ridicules, mais essayer de le rendre plus agréable dans cette situation n'est pas vraiment une option, la console doit exécuter JS correctement, et nous devons être sûrs que Chrome ne se contente pas de deviner qu'il pense que nous voulait vraiment faire autre chose.

Si vous n'aimez pas les opérateurs de virgule, vous pouvez utiliser l'affectation

x = {foo:1}.foo

Parce que tel quel

{} + {} + {}

"[object Object][object Object][object Object]"

;{} + {} + {}

"NaN[object Object]"

Fou et cohérent je peux gérer ... fou et incohérent non merci!


une REPL n'est pas la langue, c'est une REPL. Il passe des chaînes à la langue entre autres . Voici plusieurs choses que Chrome REPL fait, le langage lui-même ne le fait pas . Ils sont très utiles, donc je suis vraiment content qu'ils ne se soient pas limités au langage simple.
gman

@gman A REPL Lit une chaîne, l'évalue, imprime les résultats, puis se prépare à lire le prochain morceau de code dynamique. Rien dans la page liée n'était un JavaScript incorrect. La variable "$ _" étendue au contexte de la console est clairement une commodité qui n'a de sens que dans une REPL. Néanmoins, "$ _" est un nom de variable valide, les autres ne sont que des fonctions et des classes normales appelées avec du JavaScript normal.
James Wakefield le

Je ne sais pas quel est votre point. Mon point est que la langue est une chose, l'environnement dans lequel elle s'exécute en est une autre. Vous avez donné un exemple dans votre réponse. Dans JS {foo:1}et {foo:1}//produire la même chose. Dans Chrome JS REPL, ils ne le font pas. Le REPL fait plus que simplement évaluer JS. Il traite les chaînes et décide de différentes choses.
gman le

var x = eval('{a:1}')En JavaScript valide, x vaut maintenant 1, pas l'objet le plus intuitif {a: 1}. Oui, c'est bizarre, mais vous ne pouvez pas simplement changer la langue parce que cela fait des choses bizarres. Tout autre que les chaînes JSON sont interprétés comme JavaScript et évalués. Taper 0,avant de coller le JSON n'est pas difficile, sinon je serais heureux avec un avertissement indiquant que la chaîne a été interprétée comme un objet au lieu de JavaScript pour plus de commodité.
James Wakefield le
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.