javascript ecmascript-6 formal-semantics

javascript - ¿Cuáles son las semánticas precisas de las funciones de nivel de bloque en ES6?



ecmascript-6 formal-semantics (2)

Por lo que puedo ver, strict refiere a la ranura interna [[Strict]] del objeto de función.

No y sí. Se refiere a la rigurosidad de la función ( o script ) en la que se produce el bloque que contiene la declaración de función. No a la rigurosidad de la función que se declara (o no).

Las "extensiones web" solo se aplican al código descuidado (no estricto), y solo si la apariencia de la declaración de función es "sensata", es decir, si su nombre no choca con un parámetro formal o léxico variable declarada

Tenga en cuenta que no hay diferencia entre el código estricto y el descuidado sin la semántica de compatibilidad web. En ES6 puro, solo hay un comportamiento para las declaraciones de funciones en bloques.

Así que básicamente tenemos

| web-compat pure -----------------+--------------------------------------------- strict mode ES6 | block hoisting block hoisting sloppy mode ES6 | it''s complicated ¹ block hoisting strict mode ES5 | undefined behavior ² SyntaxError sloppy mode ES5 | undefined behavior ³ SyntaxError

1: Ver abajo. Se solicitan advertencias.
2: normalmente, se SyntaxError un SyntaxError
3: La nota en ES5.1 §12 habla de " variaciones significativas e irreconciliables entre las implementaciones " (como these ). Se recomiendan advertencias.

Entonces, ¿cómo se comporta una implementación de ES6 con compatibilidad web para una declaración de función en un bloque en una función de modo descuidado con semántica heredada?
En primer lugar, la semántica pura aún se aplica . Es decir, la declaración de función se eleva a la parte superior del bloque léxico.
Sin embargo, también hay una declaración var que se eleva a la parte superior de la función de cierre.
Y cuando se evalúa la declaración de función (en el bloque, como si se cumpliera como una declaración), el objeto de función se asigna a esa variable con ámbito de función.

Esto se explica mejor por código:

function enclosing(…) { … { … function compat(…) { … } … } … }

funciona igual que

function enclosing(…) { var compat₀ = undefined; // function-scoped … { let compat₁ = function compat(…) { … }; // block-scoped … compat₀ = compat₁; … } … }

Sí, eso es un poco confuso, ya que tiene dos enlaces diferentes (indicados con los subíndices 0 y 1) con el mismo nombre. Entonces ahora puedo responder sucintamente a sus preguntas:

Visible fuera del bloque?

Sí, como una var . Sin embargo, hay un segundo enlace que solo es visible dentro del bloque.

¿Alzado?

Sí dos veces.

¿Hasta qué punto?

Tanto para la función (aunque inicializada con undefined ) como para el bloque (inicializada con el objeto de función).

"TDZ"?

No en el sentido de la zona muerta temporal de una variable declarada léxicamente ( let / const / class ) que arroja referencias, no. Pero antes de que se encuentre la declaración de función en la ejecución del cuerpo, la variable de ámbito de función undefined está undefined (especialmente antes del bloque), y también obtendrá una excepción si intenta llamarla.

Solo como referencia: en ES6, el comportamiento descrito anteriormente se especificó solo para bloques en ámbitos de función. Desde ES7, lo mismo se aplica a los bloques en los ámbitos eval y global.

Estoy tratando de entender las nuevas funciones estandarizadas de nivel de bloque en ES6 leyendo la especificación en bruto. Mi comprensión superficial fue:

  • Las declaraciones de funciones a nivel de bloque están permitidas en ES6.
  • Se elevan hasta la parte superior del bloque.
  • En modo estricto, no son visibles fuera del bloque contenedor.

Sin embargo, esto se complica aún más por el hecho de que parte de estas semánticas se especifican como "opcionales" y solo obligatorias para los navegadores web ( Anexo B ). Entonces me gustaría tener la siguiente tabla llena:

| Visible outside of block? | Hoisted? Up to which point? | "TDZ"? | ------------------------------------------------------------------------------------------------------------------------ | Non-strict mode, no "web extensions" | | | | | Strict mode, no "web extensions" | | | | | Non strict mode, with "web extensions | | | | | Strict mode, with "web extensions" | | | |

Tampoco está claro para mí qué significa "modo estricto" en este contexto. Esta distinción parece introducirse en el Anexo B3.3 , como parte de algunos pasos adicionales para la ejecución en tiempo de ejecución de una declaración de función:

1. If strict is false, then ...

Sin embargo, hasta donde puedo ver, strict refiere a la ranura interna [[Strict]] del objeto de función. ¿Esto significa que:

// Non-strict surrounding code { function foo() {"use strict";} }

debe considerarse "modo estricto" en la tabla anterior? Sin embargo, eso contradice mi intuición inicial.

Tenga en cuenta que estoy interesado principalmente en la especificación ES6 en sí misma, independientemente de las inconsistencias de implementación reales.


No estoy seguro de dónde viene tu confusión. De acuerdo con 10.2.1 está muy claro lo que está o no "en modo estricto". En su muestra, la ranura interna de foo [[Strict]] sería true y estará en modo estricto, pero el bloque que lo aloja no lo será. La primera oración (la que citó) se relaciona con el bloque de alojamiento, no con el contenido generado dentro de él. El bloque en su fragmento no está en modo estricto y, por lo tanto, esa sección se aplica a él.