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
źródło
źródło
b.z = 1
ib.e = 1
najpierw wykonałbym (biorąc pod uwagę prawostronne skojarzenie=
), a następniea.x.y.z = ...
wykonałby i zawiódł; dlaczegob
przypisanie mija w jednym przypadku, a nie w drugim?y
nie istniejea.x
; ale to prawda w obu przypadkach. Dlaczego uniemożliwia przypisanie po prawej stronie w drugim przypadku, a nie w pierwszym? Czym różni się kolejność wykonywania? (Wspomniałem o błędzie składniowym, ponieważ czas wystąpienia błędu składniowego bardzo różni się od czasu błędu wykonania).Odpowiedzi:
Właściwie, jeśli poprawnie przeczytasz komunikat o błędzie, przypadek 1 i przypadek 2 generują różne błędy.
Sprawa
a.x.y
:Sprawa
a.x.y.z
:Chyba najlepiej opisać to krok po kroku prostym angielskim.
Przypadek 1
Przypadek 2
W komentarzach Solomon Tam znalazł dokumentację ECMA dotyczącą operacji przypisania .
źródło
Kolejność operacji jest jaśniejsza, gdy używasz operatora przecinka w notacji nawiasów, aby zobaczyć, które części są wykonywane, gdy:
Patrząc na specyfikację :
PutValue
co rzucaTypeError
:Nic nie może być przypisane do właściwości
undefined
-[[CanPut]]
wewnętrzna metodaundefined
zawsze zwracafalse
.Innymi słowy: tłumacz analizuje lewą stronę, a następnie prawą stronę, a następnie zgłasza błąd, jeśli nie można przypisać właściwości po lewej stronie.
Kiedy to zrobisz
Lewa strona jest pomyślnie analizowana do momentu
PutValue
wywołania; fakt, że.x
właściwość jest oceniana jako,undefined
jest brany pod uwagę dopiero po przeanalizowaniu prawej strony. Interpreter widzi to jako „Przypisz jakąś wartość do właściwości„ y ”z undefined”, a przypisanie do właściwościundefined
tylko wrzuca do środkaPutValue
.W przeciwieństwie:
Interpreter nigdy nie dochodzi do punktu, w którym próbuje przypisać
z
właściwość, ponieważ najpierw musi rozstrzygnąća.x.y
wartość. Jeśli zostaniea.x.y
rozstrzygnięty na wartość (nawet doundefined
), byłoby OK - błąd zostałby wrzucony do środka,PutValue
jak powyżej. Jednak dostęp do obiektua.x.y
generuje błąd, ponieważy
nie można uzyskać dostępu do właściwościundefined
.źródło
Rozważ następujący kod:
Ogólny zarys kroków wymaganych do wykonania kodu jest następujący ref :
a.x.y
zwraca odniesienia ref składający się z wartości bazoweja.x
(nieokreślony) i nazwa odniesienia (y
).y
undefined na wartość. Powinno to spowodować zgłoszenie wyjątku TypeError ref .źródło