2012-05-04 8 views
17

Supongamos que estoy intentando ejecutar este fragmento de JavaScript. Suponga que los vars y métodos no declarados se declaran en otro lugar, arriba, y que something y somethingElse evalúan a boolean-true.Alcance de JavaScript en un bloque de prueba

try { 
    if(something) { 
     var magicVar = -1; 
    } 

    if(somethingElse) { 
     magicFunction(magicVar); 
    } 
} catch(e) { 
    doSomethingWithError(e); 
} 

Mi pregunta es: ¿cuál es el alcance de magicVar y está bien para pasar en magicFunction como lo he hecho?

+1

Me parece que esto es sólo una cuestión acerca ámbito de las variables, no alcance variable dentro de un bloque try. –

Respuesta

17

Javascript tiene alcance de la función.Eso significa que magicvar existirá desde el principio de la función que se declaró hasta el final de esa función, incluso si esa sentencia no se ejecuta alguna vez. Esto se llama variable que eleva. Lo mismo ocurre con las declaraciones de funciones, que a su vez se llama función de elevación.

Si la variable se declara en alcance global, será visible a todo. Esta es una de las razones por las cuales las variables globales son consideradas malas en Javascript.

Su ejemplo pasará undefined en magicFunction si something es falso, porque magicVar no ha sido asignado a nada.

Si bien este es el Javascript técnicamente válido, generalmente se considera un estilo incorrecto y no pasará correctores de estilo como jsLint. Extremadamente Javascript poco intuitivo como éste se ejecutará sin ningún error

alert(a); //alerts "undefined" 
var a; 

Pop Quiz: ¿Qué hace el siguiente código?

(function() { 
    x = 2; 
    var x; 
    alert(x); 
})(); 
alert(x); 
+1

El ejemplo que has dado no es del todo bueno porque de todos modos no estaba "definido", porque 'window.a' está' indefinido' – gdoron

+0

@gdoron No estoy seguro de ver a qué atenerse. Si solo intenta ejecutar 'alert (a)' por sí mismo, lanzará un error como 'a is 'undefined''. –

+0

La cosa es que 'a' _puede ser indefinido porque no está definido en el ámbito externo. Echa un vistazo a esta [demo] (http://jsfiddle.net/gdoron/H8c4n/3/) Si eliminas 'var x', obtienes el mismo resultado. – gdoron

1

Con var, las variables existen desde el comienzo de la función hasta el final de la misma, sin importar dónde se declaren, o incluso si alguna vez se llega a la declaración. Sin embargo, serán undefined hasta que se les asigne otro valor.

Así, en su caso, si es falso, pero somethingsomethingelse es cierto, se le llama magicFunction con ser su primer argumento undefined.

El let palabra clave, creada en Javascript 1.9 y disponible (a partir de hoy, 3 de mayo rd 2012, y hasta donde yo sé) sólo en Firefox, declara variables con la semántica de ámbito es probable que estés acostumbrado.

5
  • En las funciones de javascript solamente se crea un nuevo contexto-cierre.
  • Cada definición de una variable es realmente una declaración de la variable en la parte superior de su alcance y una asignación en el lugar donde está la definición.

var

  • función de ámbito de
  • polipasto a la parte superior de su función
  • redeclarations del mismo nombre en el mismo ámbito hay-ops

Usted puede que quiera leer MDN scope cheat sheet

Debido a hoisting Incluso puede hacer cosas como esta:

function bar() { 
    var x = "outer"; 

    function foo() { 
     alert(x); // {undefined} Doesn't refer to the outerscope x 
     // Due the the var hoising next:   
     x = 'inner'; 
     var x; 
     alert(x); // inner 

    } 
    foo(); 
} 

bar();​ 

bar();​ 

Demo

Por lo tanto la función foo se convierte en algo parecido a esto:

function foo() { 
    var x; 
    alert(x); // {undefined} Doesn't refer to the outerscope x 
    // Due the the var hoising next:   
    x = 'inner'; 
    alert(x); // inner 
}​ 

Mi pregunta es: ¿cuál es el alcance de magicVar an d ¿está bien pasarlo a la función mágica como lo hice?

Definir bien ..., Si el código es válido, pero es menos legible a continuación, si las declaraciones de variables estaban en la parte superior, eso es todo.

+0

¡Estoy desgarrado! Me encantan tanto la tuya como la de Peter Olson. Tener un voto positivo :) – user5243421

+0

@DarrenGreen. **:) ** No te sientas mal. Solo elige la mejor respuesta que crees que tienes. (No me gusta la idea de Stackoverflow de que las respuestas aceptadas aparezcan en la parte superior {¿oí _hoisting_? :)}, no tiene sentido que el tipo que probablemente tenga menos conocimiento sobre la pregunta decida cuál es la mejor respuesta .) Si es la respuesta de Peter, estoy de acuerdo, no compito con las respuestas. – gdoron

+0

El enlace de la hoja de referencia se considera contenido obsoleto. Me encantan las grandes barras de advertencia en esa página, ¡no te lo vas a perder! jaja – jcollum

3

Debido a javascript "elevación" (google), el código de declaración de variables se traduce como:

function yourFunction() { 
    var magicVar; 
    try { 
     if(something) { 
      magicVar = -1; 
     } 

     if(somethingElse) { 
      magicFunction(magicVar); 
     } 
    } catch(e) { 
     doSomethingWithError(e); 
    } 

} //end of your function 

"elevación" se mueve todas las declaraciones de variables a la parte superior de la función. Entonces magicVar está disponible en todas partes en la función, pero no está definido hasta que le dé un valor.

Su variable tiene un alcance de función.

14

Un montón de otras buenas respuestas sobre cómo Javascript maneja esto con var, pero pensé que me gustaría abordar la situación let ...

Si una variable se define con let dentro del bloque try, no será en el alcance dentro del bloque (s) catch (o finally). Tendría que definirse en el bloque adjunto.

Por ejemplo, en el siguiente bloque de código, la salida de la consola será "fuera":

let xyz = "Outside"; 

try { 
    let xyz = "Inside"; 

    throw new Error("Blah"); 
} catch (err) { 
    console.log(xyz); 
} 
Cuestiones relacionadas