Je regarde la grammaire ECMA-262 pour une définition du code suivant ci-dessous:
const v = (! + [] + []); const c = (false + []); console.log(v); console.log(c);
Qu'est-ce que DERRIÈRE?
Jusqu'à présent, je n'ai rien trouvé d'utile, est-ce que quelqu'un sait pourquoi il donne ces résultats ou a des références à ce sujet?
3 Réponses :
const v = (! + [] + []); const c = (false + []); console.log(v); console.log(c);
Si vous supprimez le .length
, vous voyez que les résultats sont:
true
et false
et que ceux-ci (les résultats des opérations +
) ne sont pas des tableaux mais des chaînes, et true
fait 4 caractères et false
vaut 5.
En utilisant votre lien ci-dessus, il semble que ceci soit au moins en partie pertinent:
12.7.3 L'opérateur Addition (+) p >
REMARQUE L'opérateur d'addition effectue soit une concaténation de chaînes, soit une addition numérique.
Que voulez-vous dire avec que ce ne sont pas des tableaux mais des chaînes
? []
sont en effet des tableaux, mais ces tableaux sont convertis en chaînes.
@ t.niese "ces" fait référence à v
( true
) et c
( false
), pas aux opérandes à +
.
En effet, lorsque vous essayez d'appliquer un opérateur à une structure de données différente, le moteur JavaScript s'applique coercition .
Dans le premier cas, ce qu'il fait est:
Convertit le premier [] en primitive, ce qui est effectué en appelant la méthode toString () du tableau. La méthode toString joint toutes les valeurs du tableau à une chaîne. Si vous avez quelque chose comme (false + [1,2,3])
, vous obtiendrez: false1,2,3
La deuxième étape consiste à amener le booléen dans le contexte String
Maintenant que nous avons toutes les valeurs dans la même structure de données, il va simplement les concaténer toutes
Dans votre cas, (! + [] + [])
est évalué à «vrai» qui a la longueur de 4.
Le livre You Don ' t Know JS: Types & Grammar est un joyau pour comprendre tous ces types d'opérations étranges que le moteur JavaScript fait.
MODIFIER : comme Felix Kling le suggérait! L'opérateur a un rôle différent dans l'évaluation de (! + [] + [])
.
Dans ce cas, ce qui se passe est que:
! + []
est évalué à vrai. C'est parce que ! + []
les met dans un contexte booléen où l'opération [toNumber] est appliquée sur [] qui est 0
et ! 0
est vrai
true + []
est évalué à 'true'
. En effet, lorsque vous essayez d'ajouter un booléen avec un objet (le tableau est dérivé de l'objet), l'opération [toString] est appliquée aux deux éléments.
FWIW, ! + [1,2,3]
est vrai
. !
est un opérateur, pas une valeur.
@FelixKling vous avez raison sur la première phrase. Quant à l'autre, une fois! est introduit dans un contexte booléen, je pense que vous pouvez le voir comme une valeur de ce point de vue.
"vous pouvez le voir comme une valeur de ce point de vue" Non. Les opérateurs ne sont pas des valeurs, les fonctionnent sur des valeurs. Je n'ai mentionné cela que parce que votre exemple semblait impliquer que !
est converti en false
.
Je pense que cette réponse passe à côté du fait que !
agit sur le nombre retourné par unaire plus + []
et implique plutôt que !
en lui-même peut être utilisé comme valeur qui ferait partie d'une opération x + y
si +
était l'opérateur d'addition. Ce n'est pas ce qui se passe. la première ligne serait plus (! (+ [])) + []
ce qui équivaut à ! 0 + []
.
En fait, pour comprendre pourquoi vous obtenez ce résultat, vous devez réfléchir à la manière dont l'expression est évaluée (c'est-à-dire dans quel ordre?). Si nous observons votre première expression:
const v = (! + [] + []); console.log("value: " + v, "type: " + typeof(v));
nous pouvons voir qu'il existe un opérateur logique (le NOT logique !
), un opérateur unaire ( + ) et un opérateur arithmétique, en fait l'addition
+
. Si nous prenons en compte l'ordre d'évaluation de cette expression, nous pouvons l'écrire comme ceci:
const v = "true" + ""; // or simply "true".
Maintenant, la première expression évaluée ici est + [] et de la documentation de opérateur unaire plus que vous obtenez:
L'opérateur unaire plus précède son opérande et s'évalue en son opérande mais tente de le convertir en nombre, si ce n'est déjà fait ...
En fait, l'évaluation précédente aboutit à 0
(une contrainte se produit lorsque le tableau vide est transtypé en nombre) comme vous pouvez le vérifier dans l'exemple suivant:
const v = ( true + [] );
Alors maintenant, l'expression est réduite à
console.log(!0);
Encore une fois, en lisant une documentation sur ce opérateur logique non que vous pouvez trouver:
Renvoie false si son unique opérande peut être converti en vrai; sinon, renvoie vrai.
Donc, ! 0
est réduit à true
(une autre coercition se produit lorsque le nombre zéro est converti en type booléen) comme vous pouvez le vérifier à la suite exemple:
const v = ( (!0) + [] );
Nous avons maintenant l'expression suivante où le addition entre en jeu:
console.log(+[]);
L'opérateur d'addition produit la somme des opérandes numériques ou de la concaténation de chaînes.
Dans ce cas, l'opérateur effectuera une concaténation de chaînes puisque les opérandes ne sont pas des nombres. Donc, voici où une nouvelle coercition (essentiellement un cast implicite de types) a lieu à nouveau, car elle doit convertir les deux opérandes en chaînes:
true
est converti en chaîne "true"
à l'aide de la méthode toString ()
du développeur Type booléen . []
est converti en chaîne vide ""
à l'aide de la méthode toString ()
disponible de Type Array . Et enfin, notre expression est réduite à:
const v = ( (!(+[])) + [] );
const v = (! + [] + []);
La deuxième expression devrait être facile à analyser par vous-même maintenant, car il s'agit d'une version simplifiée de la première.
Regardez l'opérateur
+
dans la spécification (il contraint ses arguments)Voir l'explication ici: 2ality.com/2012/01/object-plus-object. html
"vrai" .longueur = 4, "faux" .longueur = 5
Voir ceci
Copie possible de
(! [] + []) [+ []]
… Expliquez pourquoi cela fonctionne a>S'il vous plaît, ne changez pas l'objectif de votre question initiale, cela aidera à maintenir la cohérence avec les réponses