what the statement script que node missing es6 enable javascript eval ecmascript-5

javascript - the - use strict que es



Llamada de evaluación indirecta en modo estricto (1)

tl; dr

El segundo (0, eval)(''var a = 1;''); El caso no es, de hecho, una llamada directa.

Puedes ver esto más prevalentemente en:

(function(){ "use strict" var x = eval; x("var y = 10"); // look at me all indirect window.y;// 10 eval("var y = 11"); window.y;// still 10, direct call in strict mode gets a new context })();

El tema se puede ver en:

Si el código eval es un código estricto, entonces (yo: corregir contexto)

Pero el código de evaluación estricto se define como:

El código de evaluación es un código de evaluación estricto si comienza con un Prólogo directivo que contiene una directiva de uso estricto o si la llamada a eval es una llamada directa.

Como la llamada no es directa, el código de evaluación no es un código de evaluación estricto, y la ejecución se encuentra en el ámbito global.

Ante todo una gran pregunta.

"Código de evaluación" es más general que la llamada directa o indirecta a eval .

Revisemos la especificación exacta para la función eval

15.1.2.1 eval (x)

Cuando se llama a la función eval con un argumento x, se toman los siguientes pasos:

  1. Si Type (x) no es String, devuelve x.

  2. Deje que prog sea el código ECMAScript que es el resultado de analizar x como un Programa. Si el análisis falla, lance una excepción SyntaxError (pero vea también la cláusula 16).

  3. Deje que evalCtx sea el resultado de establecer un nuevo contexto de ejecución (10.4.2) para el código de evaluación prog.

  4. Que el resultado sea el resultado de evaluar el programa prog.

  5. Salga del contexto de ejecución en ejecución evalCtx, restaurando el contexto de ejecución anterior. ...

Entonces, exploremos lo que nos dice 10.4.2, usted citó eso, en concreto, veamos la primera cláusula:

Si no hay un contexto de llamada o si el código eval no está siendo evaluado por una llamada directa (15.1.2.1.1) a la función eval, entonces ... Inicialice el contexto de ejecución como si fuera un contexto de ejecución global

Entonces, ¿qué es una llamada directa?

Una llamada directa a la función eval es una que se expresa como una expresión de llamada que cumple las dos condiciones siguientes:

La referencia que es el resultado de la evaluación de la expresión miembro en la expresión de llamada tiene un registro de entorno como su valor base y su nombre de referencia es "eval".

El resultado de llamar a la operación abstracta GetValue con esa referencia como argumento es la función incorporada estándar definida en 15.1.2.1.

Entonces, ¿cuál es la MemberExpression de MemberExpression en ambos casos?

En eval(''var a = 1;''); de hecho, el resultado de evaluarla tiene un nombre de referencia eval y llamar a la resolución GetValue devuelve la función incorporada.

En (0, eval)(''var a = 1;''); el resultado de evaluar la expresión miembro no tiene un nombre de referencia eval . (Se resuelve a la función incorporada en GetValue sin embargo).

¿Cuáles son los nombres de referencia de todos modos?

La sección 8.7 en la especificación nos dice:

Una referencia es un enlace de nombre resuelto. Una referencia consta de tres componentes, el valor base, el nombre de referencia y el indicador de referencia estricto de valor booleano. El valor base es undefined, un Object, un Boolean, un String, un Number o un registro de entorno (10.2.1). Un valor base de indefinido indica que la referencia no se pudo resolver en un enlace. El nombre de referencia es una cadena.

Esto nos obliga a buscar en GetReferencedName :

GetReferencedName (V). Devuelve el componente de nombre de referencia de la referencia V.

Entonces, mientras que la expresión (0,eval) === eval es verdadera, al evaluar la función, esto es en realidad una llamada indirecta debido a la denominación.

¿Puedo ofrecer el constructor de Function lugar :)?

Entiendo cómo funciona eval() en contextos no estrictos, sin embargo, el caso de usar eval() en modo estricto me ha dejado completamente aturdido. Cuando se llama a eval() directamente en el alcance global, las variables se mantienen dentro del nuevo alcance eval() :

''use strict''; eval(''var a = 1;''); console.log(a); // ReferenceError: a is not defined

Sin embargo, si realizo una llamada indirecta a eval() en el ámbito global (debería ser lo mismo, ¿no?), Actúa como si no estuviera en modo estricto (si no me crees, consulta esta JSFiddle ) :

''use strict''; (0, eval)(''var a = 1;''); // indirect call to eval console.log(a); // 1???

Si no entiende qué hace (0, eval) , consulte ¿Por qué la página principal de google usa la sintaxis (0, obj.func) (args)? .

Al menos según mi comprensión de cómo se supone que eval() funciona en modo estricto, está destinado a (no importa si se llama a directa eval() directa o indirectamente) crear un nuevo ámbito para las variables definidas en la llamada eval() , Sin embargo, este no parece ser el caso aquí. La especificación dice lo siguiente:

10.4.2 Entrar en el código de evaluación

Los siguientes pasos se realizan cuando el control ingresa en el contexto de ejecución para el código eval:

  1. Si no hay un contexto de llamada o si el código eval no está siendo evaluado por una llamada directa ( 15.1.2.1.1 ) a la función eval, entonces,

    a. Inicialice el contexto de ejecución como si fuera un contexto de ejecución global utilizando el código eval como C como se describe en 10.4.1.1 .

  2. Más,

    a. Establezca ThisBinding en el mismo valor que ThisBinding del contexto de ejecución de llamada.
    segundo. Establezca ThisBinding en el mismo valor que ThisBinding del contexto de ejecución de llamada.
    do. Establezca ThisBinding en el mismo valor que ThisBinding del contexto de ejecución de llamada.

  3. Si el código de evaluación es un código estricto , entonces

    a. Deja que strictVarEnv sea ​​el resultado de llamar a NewDeclarativeEnvironment pasando el ThisBinding como argumento.
    segundo. Establezca ThisBinding en strictVarEnv .
    do. Establezca ThisBinding en strictVarEnv .

  4. Realice la creación de instancias de vinculación de declaración como se describe en 10.5 utilizando el código eval.

Este es el caso en todos los navegadores principales, incluyendo (pero no limitado a) Internet Explorer 10, Chrome 30 y Firefox 24, ya que todos ellos tienen el mismo comportamiento, no creo que sea probable que sea un error. ¿No están destinados ambos a hacer lo mismo? Y si no, ¿por qué es así?

Nota: por favor , no me diga que no use eval() (sí, conozco los "peligros" de usar eval() ). Simplemente quiero entender la lógica detrás de esto, lo que me confunde por completo.