considera el siguiente código
var myVar = 'Hola'; { let myVar; myVar = 'Hello' } en la línea 4 ( myVar = 'Hello' ) estamos usando el operador de asignación
Ahora, cuando estaba mirando ecma262 en la evaluación de operadores de asignación
dice que el lado izquierdo en los operadores de asignación es LeftHandSideExpression y el lado derecho es AssignmentExpression
en otras palabras parece que
LeftHandSideExpression = AsignaciónExpresión
¿Alguien puede explicarme cómo se evaluará myVar? si se supone que es LeftHandSideExpression ?
La pieza principal que hay que entender es que evaluate en este contexto significa que estamos ejecutando estas Runtime Semantics: Evaluation para las diversas piezas gramaticales del lenguaje. En el caso de
myVar = 'Hello' si nos fijamos en 13.15.2 Runtime Semantics: Evaluation para la evaluación de AssignmentExpression la línea
1.a. Sea lref el resultado de evaluar LeftHandSideExpression.
profundizará a través de los diversos pasos hasta que finalmente termine ejecutando 13.1.3 Semántica de tiempo de ejecución: evaluación que define el comportamiento de evaluación de myVar .
La clave si pasa por esto es que lref no evalúa a un valor JS, evalúa a un tipo de Reference Record , que no es un valor que el código JS conoce, pero representa el concepto de una ubicación donde un valor puede ser asignado. En el caso de su fragmento, es básicamente una referencia al ámbito donde se encuentra la lista de variables y el nombre de la variable, por lo que cuando la asignación se realiza más tarde, se resuelve por completo más tarde.
Este es el comportamiento de evaluar primero el lado izquierdo más importante para ejemplos como este:
foo().bar = val(); porque evaluar la izquierda significa que foo() se ejecuta antes que val() , que es lo que esperarías. En este caso, foo() se ejecuta y luego obtenemos un Reference Record con el valor de retorno de foo() como destino de la asignación y bar como el nombre de la propiedad a asignar.
Volviendo a 13.15.2 Runtime Semantics: Evaluation , llegamos a
1.e Realizar? PonerValor(lref, rval).
que es donde ocurre la asignación final. rval es la propia cadena "Hello" ya que ha sido evaluada. Si echa un vistazo a 6.2.4.6 PutValue (V, W) , probablemente pueda adivinar que la tercera sección es con lo que terminamos para una asignación de variable
entonces en tu caso es
(<scope with closest `var/let myVar`).SetMutableBinding("myVar", "Hello", false)Dentro de la declaración del bloque, todas las variables definidas son locales, por lo que myVar dentro del bloque será "Hello" . Afuera, la variable definida con var es global, y su valor nunca cambió ya que myVar interno era una variable totalmente diferente, solo que con el mismo nombre. Entonces, el myVar externo definido con var nunca cambió de su valor inicial de "Hola" .
var myVar = "Hola"; { let myVar; myVar = "Hello"; console.log("inside:", myVar); } console.log("outside:", myVar);Puede tener diferentes cosas en el lado izquierdo como:
a = 'foo' ab = ['foo','bar'] new Object().b = ['foo','bar'] foo().b = ['foo','bar'] Para el caso simple de a = no hay mucho que hacer.
Pero para ab = , new Object().b = y foo().b = primero debe evaluar el lado izquierdo.