2010-05-18 11 views
6

En este ejemplocadena de alcance de funciones internas de JavaScript?

var a = 1; 
(function(x) { 
    function inner() { 
     alert(a); 
     alert(x); 
     alert(y); 
    } 
    var y = 3; 
    inner(); 
})(2); 

¿Cuándo se function inner se crean? durante el tiempo de ejecución o el tiempo de análisis de la función anónima externa?

¿Qué hay en la cadena de alcance de function inner?

¿Cuál es la diferencia entre el contexto de ejecución y la cadena de alcance de function inner?

Gracias por iluminarme por adelantado!

Respuesta

7

¿Cuándo se crea la función interna? durante el tiempo de ejecución o el tiempo de análisis de la función anónima externa?

Se crea uno cada vez que se ejecuta la función externa.

¿Qué es el alcance de la cadena de función interna?

Cuando lo ejecuta, esa ejecución obtiene un objeto variable (técnicamente la especificación lo llama el "objeto de enlace del entorno variable"); eso está respaldado por el objeto variable creado para la llamada a función externa que creó inner; eso está respaldado por el objeto variable global. Por lo tanto:

+------------------------------+ 
| global variable obj   | 
+------------------------------+ 
    ^
    | 
    +-----------------------------+ 
    | variable obj for outer call | 
    +-----------------------------+ 
    ^
     | 
     +-----------------------------+ 
     | variable obj for inner call | 
     +-----------------------------+ 

Lo que está en el contexto de ejecución de la función interior?

Cada llamada de función obtiene su propio contexto de ejecución. No estoy seguro de entender lo que se pregunta aquí.

Usted puede leer sobre todas estas cosas (si está dispuesto a vadear a través de la melaza de la prosa turgente) en la sección 10 de the spec, y en particular section 10.4.3: "Introducir el código de la función".

+0

contexto de ejecución se crea en tiempo de ejecución, la cadena de alcance se crea en el momento de la definición (no estoy seguro de que es el término correcto), mi pregunta es: ¿cuál es la diferencia entre el contexto de ejecución y la cadena de alcance de la función interna? ¿Cuál es el proceso de creación del contexto de ejecución? ¡Gracias! – nandin

+1

@Ding: Sí, la cadena del alcance está dictada por el lugar donde se define la función. Al mirar una función en la fuente, puede ver qué identificadores están dentro del alcance y de dónde provienen. Pero las funciones no tienen contextos de ejecución, solo * calls * para las funciones do. El contexto de ejecución incluye el objeto variable que forma el mecanismo de tiempo de ejecución de la cadena de alcance, así como otras cosas, como cuál debe ser el valor 'this'. Es evidente que tienes interés en saber realmente cómo funciona esto (¡lo cual es genial!) Y por eso solo puedo decir: lee la sección 10 (especialmente las 10.3 y 4) de la especificación para obtener más información. :-) –

9

La función inner se crea justo antes de que se ejecute la función anónima, mediante el proceso Variable Instantiation.

El [[Scope]] de inner cuando es ejecutado contiene:

  1. El objeto variable vacía de inner (está vacío porque no hay declaraciones de variables/funciones dentro de él)
  2. El objeto variable de la función anónima, que contiene x, y y inner.
  3. El objeto global, que contendrá a y otras propiedades ...
 
    Global (3)   Anonymous VO (2)  inner VO (1) 
    ________    ________    ________ 
    | a = 1 | <--------- | x = 2 | < -------- |  | 
    | ... |   | y = 3 |    ¯¯¯¯¯¯¯¯ 
    ¯¯¯¯¯¯¯¯    | inner | 
         ¯¯¯¯¯¯¯¯ 

Editar: Para aclarar su segunda pregunta:

¿Cuál es la diferencia entre el contexto de ejecución y la cadena de ámbito de la función interior?

Son dos conceptos diferentes, se crea un contexto de ejecución justo antes de que se ejecute un fragmento de código (que es can be ya sea código global, código de función o código de evaluación).

Creo que esto podría ser más fácil de explicar con su código:

var a = 1; 
(function(x) {  // Step 1 
    function inner() { 
     alert(a); 
     alert(x); 
     alert(y); 
    } 
    var y = 3; 
    inner();   // Step 3 
})(2);    // Step 2 

En el Paso 1, la función anónima es created, el alcance actual (sólo contiene el objeto global) se almacena en este momento en la propiedad de la función [[Scope]].

En el Paso 2, se ejecuta esta función anónima, un nuevo contexto de ejecución se crea (un function code execution context), en este momento se crea un nuevo entorno léxico (se crea la variable objeto de esta función), todas las funciones los identificadores de argumentos (en este caso solo x), los identificadores de declaraciones de funciones (inner) y los identificadores de declaraciones de variables (y) están vinculados como propiedades no eliminables de este nuevo objeto variable (que es el nuevo alcance léxico).

En el Paso 3 se ejecuta la función inner, esto crea un nuevo contexto de ejecución, otro objeto variable se inyecta en la cadena de ámbito, pero en este caso ya que nada está declarado dentro de inner y no tener ningún parámetros formales, será solo un objeto vacío.

Ver también this respuesta, la primera parte hablo de la declaración with pero en la segunda parte se trata de funciones.

+0

gracias CMS, como siempre, ¡excelente respuesta! – nandin

+0

Eres bienvenido @Ding, editado para responder a tu segunda pregunta ... – CMS

+0

esto es realmente difícil de leer (http://www.ecma-international.org/publications/standards/Ecma-262.htm), ¿puedes recomendar un código de motor JS de código abierto? ¿Qué hay de V8? ¡Gracias! – nandin

Cuestiones relacionadas