Quand vous essayez de faire ça :
var b1, b2;
b1 = !b2 = true;
document.write(b1, " ", b2);
Parce qu'ils sont fonctionnellement équivalents ‡ que vous êtes en train de faire :
var b1, b2;
!b2 = true;
b1 = true; //just the value of b2, not b2 itself
document.write(b1, " ", b2);
Dans la ligne !b2 = true
vous essayez d'assigner une expression qui évalue une valeur (le côté gauche) à une valeur - cela n'a absolument aucun sens. Pensez-y de cette façon :
-
!b2
est affecté à true
. !b2
est une expression et est évaluée comme un booléen. valeur non variable.
- Cela reviendrait à faire
1 + 1 = 2
. Puisque 1 + 1
est évalué à un valeur vous ne pouvez pas l'attribuer à 2
une autre valeur. Vous devez attribuer une valeur à variable car l'affectation de valeur à valeur est sémantiquement et logiquement invalide.
- Une autre façon de penser à ce qui précède est de réaliser ceci :
1 + 1
est une valeur. 2
est une valeur. Vous ne pouvez pas attribuer une valeur à une valeur, car cette dernière a déjà une valeur. Une constante telle que 2
a une valeur 2
il ne peut être modifié. Et si nous essayions 1 - 1 = 2
? 0
une constante et une valeur, ne peut être 2
car c'est une constante.
Ainsi, il est sémantiquement et logiquement invalide d'attribuer une valeur à une valeur. Vous ne pouvez pas attribuer 0
a 2
tout comme vous ne pouvez pas assigner false
a true
.
Si vous souhaitez mieux comprendre la syntaxe et la sémantique, et savoir pourquoi cette méthode génère une erreur de type ReferenceError
vous pouvez vous plonger dans le Spécification du langage ECMAScript® 2015 † . Selon le cahier des charges :
Section 12.14.1 - Opérateurs d'assignation - Sémantique statique : Erreurs précoces
AssignmentExpression : LeftHandSideExpression = AssignmentExpression
- C'est une première Référence Erreur si
LeftHandSideExpression
n'est ni un ObjectLiteral
ni un ArrayLiteral
y IsValidSimpleAssignmentTarget
de LeftHandSideExpression
est fausse.
Dónde IsValidSimpleAssignmentTarget
es:
Section 12.14.3 - Opérateurs d'assignation - Sémantique statique : IsValidSimpleAssignmentTarget
AssignmentExpression :
YieldExpression
ArrowFunction
LeftHandSideExpression = AssignmentExpression
LeftHandSideExpression AssignmentOperator AssignmentExpression
1. Faux retour.
Maintenant, regardez de nouveau votre code : b1 = !b2 = true
. b1 = !b2
est bien parce que c'est LeftHandSideExpression = AssignmentExpression
ce qui signifie que la réponse est vraie pour IsValidSimpleAssignmentTarget
. Le problème se pose lorsque nous vérifions !b2 = true
. Si nous regardons la définition de LeftHandSideExpression
:
Section 12.3 - Expressions du côté gauche
Syntaxe
LeftHandSideExpression :
NewExpression
CallExpression
(Vous pouvez consulter les définitions de NewExpression
y CallExpression
dans le lien de spécification ci-dessus)
Vous pouvez voir que !b2 = true
n'est pas un AssignmentExpression
car il ne répond pas aux critères LeftHandSideExpression = AssignmentExpression
. Cela s'explique par le fait que !b2
n'est pas un LeftHandSideExpression
également pas un ObjectLiteral
ni ArrayLiteral
donc IsValidSimpleAssignmentTarget
retourne false, ce qui déclenche la ReferenceError
. Notez que l'erreur est une début erreur ce qui signifie qu'il est lancé avant l'exécution de tout code, comme indiqué dans le document intitulé Commentaire de @Bergi .
Vous pouvez lutter contre ce problème en procédant de l'une ou l'autre des manières suivantes, en fonction du résultat que vous souhaitez obtenir :
b1 = !(b2 = true);
Avec des parenthèses, l'intérieur des parenthèses a la priorité sur l'extérieur. De cette façon, b2
est attribué, et comme il est true
à l'intérieur des parenthèses évalue à true
. Ensuite, c'est équivalent à :
b1 = !(true);
Comme à l'intérieur des parenthèses est évalué à true
comme indiqué ci-dessus. b1
sera l'opposé de b2
comme prévu, et b2
sera true
.
Si vous vouliez b1
à être true
y b2
à être false
restructurer la déclaration comme suit :
b2 = !(b1 = true);
De cette façon, c'est l'exact opposé de ce qui précède, ce qui donne b1 = true
et b2 = false
.
‡ Comme @Bergi l'a mentionné dans les commentaires, b1
est affecté à l'opérande de droite, true
dans ce cas, pas !b2
.
† Bien que la plupart des navigateurs ne prennent actuellement pas en charge toutes les fonctionnalités de l'ECMAScript 6 (2015), et utilisent plutôt ECMAScript 5.1 (2011) la spécification est la même pour les deux versions. Toutes les définitions sont les mêmes, et donc l'explication est toujours valable.
13 votes
En réalité, vous essayez de faire :
var b1, b2; !b2 = true; b1 = b2;
ce qui est évidemment faux. Vous ne pouvez pas assigner une expression à une valeur...0 votes
B2 n'est pas une fonction qui vérifie si c'est vrai ou faux vous devriez le mettre sur une parenthèse comme si vous faisiez une référence de chaînage de condition peut être vraie si elles ont des données égales