var a = {}
var b = {}
try{
a.x.y = b.e = 1 // Uncaught TypeError: Cannot set property 'y' of undefined
} catch(err) {
console.error(err);
}
console.log(b.e) // 1
var a = {}
var b = {}
try {
a.x.y.z = b.e = 1 // Uncaught TypeError: Cannot read property 'y' of undefined
} catch(err) {
console.error(err);
}
console.log(b.e) // undefined
javascript
operators
order-of-execution
Kevin Askin
la source
la source
b.z = 1
etb.e = 1
exécuter en premier (étant donné l'associativité à droite=
), puisa.x.y.z = ...
exécuter et échouer; pourquoi l'b
affectation passe-t-elle dans un cas mais pas dans l'autre?y
n'existe pas sura.x
; mais c'est vrai dans les deux cas. Pourquoi empêche-t-il l'affectation du côté droit dans le second cas mais pas dans le premier? Qu'est-ce qui est différent dans l'ordre d'exécution? (J'ai mentionné une erreur de syntaxe car le timing de l'erreur de syntaxe est très différent de celui d'une erreur d'exécution.)Réponses:
En fait, si vous lisez correctement le message d'erreur, les cas 1 et 2 génèrent des erreurs différentes.
Cas
a.x.y
:Cas
a.x.y.z
:Je suppose qu'il est préférable de le décrire par une exécution étape par étape dans un anglais simple.
Cas 1
Cas 2
Dans les commentaires, Solomon Tam a trouvé cette documentation ECMA sur l'opération d'affectation .
la source
L'ordre des opérations est plus clair lorsque vous exploitez l'opérateur virgule dans la notation entre crochets pour voir quelles parties sont exécutées lorsque:
En regardant les spécifications :
PutValue
est ce qui jette leTypeError
:Rien ne peut être affecté à une propriété de
undefined
- la[[CanPut]]
méthode interne deundefined
retournera toujoursfalse
.En d'autres termes: l'interpréteur analyse le côté gauche, puis analyse le côté droit, puis renvoie une erreur si la propriété sur le côté gauche ne peut pas être affectée.
Quand tu fais
Le côté gauche est analysé avec succès jusqu'à ce qu'il
PutValue
soit appelé; le fait que la.x
propriété soit évaluéeundefined
n'est pas pris en compte tant que le membre droit n'a pas été analysé. L'interpréteur le voit comme "Attribuer une valeur à la propriété" y "d'undefined", et l'assigner à une propriété deundefined
ne jette qu'à l'intérieurPutValue
.En revanche:
L'interpréteur n'atteint jamais le point où il essaie d'attribuer à la
z
propriété, car il doit d'abord se résoudrea.x.y
à une valeur. Sia.x.y
résolu à une valeur (même àundefined
), ce serait OK - une erreur serait jetée à l'intérieurPutValue
comme ci-dessus. Mais l' accèsa.x.y
génère une erreur, car la propriétéy
n'est pas accessible surundefined
.la source
Considérez le code suivant:
Les grandes lignes des étapes requises pour exécuter le code sont les suivantes réf :
a.x.y
retourne une référence ref composée d'une valeur de basea.x
(non définie) et d'un nom référencé (y
).y
de indéfini sur la valeur. Ceci est censé lancer une exception TypeError ref .la source