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
fonte
fonte
b.z = 1
eb.e = 1
executaria primeiro (dada a associatividade à direita ativada=
), depoisa.x.y.z = ...
executaria e falharia; por que ab
atribuição é aprovada em um caso, mas não no outro?y
não existe ema.x
; mas isso é verdade em ambos os casos. Por que impede a atribuição do lado direito no segundo caso, mas não no primeiro? O que é diferente na ordem de execução? (Eu mencionei o erro de sintaxe porque o tempo no erro de sintaxe é muito diferente daquele de um erro de tempo de execução.)Respostas:
Na verdade, se você ler a mensagem de erro corretamente, o caso 1 e o caso 2 geram erros diferentes.
Caso
a.x.y
:Caso
a.x.y.z
:Acho que é melhor descrevê-lo pela execução passo a passo em um inglês fácil.
Caso 1
Caso 2
Nos comentários, Solomon Tam encontrou esta documentação ECMA sobre a operação de atribuição .
fonte
A ordem das operações é mais clara quando você explora o operador vírgula dentro da notação de colchetes para ver quais partes são executadas quando:
Olhando para as especificações :
PutValue
é o que lança oTypeError
:Nada pode ser atribuído a uma propriedade de
undefined
- o[[CanPut]]
método interno deundefined
sempre retornaráfalse
.Em outras palavras: o intérprete analisa o lado esquerdo, a seguir analisa o lado direito e, a seguir , lança um erro se a propriedade do lado esquerdo não puder ser atribuída.
Quando você faz
O lado esquerdo é analisado com sucesso até que
PutValue
seja chamado; o fato de a.x
propriedade ser avaliada comoundefined
não é considerado até que o lado direito seja analisado. O intérprete vê isso como "Atribuir algum valor à propriedade" y "de undefined", e atribuir a uma propriedadeundefined
apenas joga dentroPutValue
.Em contraste:
O intérprete nunca chega ao ponto em que tenta atribuir à
z
propriedade, porque primeiro deve resolvera.x.y
para um valor. Sea.x.y
resolvido para um valor (mesmo paraundefined
), estaria tudo bem - um erro seria lançado dentroPutValue
como acima. Mas o acessoa.x.y
gera um erro, porque a propriedadey
não pode ser acessada emundefined
.fonte
Considere o seguinte código:
O esboço das etapas necessárias para executar o código é o seguinte ref :
a.x.y
retorna uma referência ref consistindo de valor basea.x
(indefinido) e nome referenciado (y
).y
de undefined para o valor. Isso deve lançar uma referência de exceção TypeError .fonte