2010-10-19 10 views
5

Si una variable podría ser definido en una función, incluso si no se asigna ningún valor, se convierte en una variable localNo hay necesidad de definir una variable dos veces

así, es TESTB() programación mejor ?

var test = 'SNAP!' 
function testA(boolean) { 
    if (boolean) var test = 'OK'; 
    else var test = null; 
    alert(test); 
} 
function testB(boolean) { 
    if (boolean) var test = 'OK'; 
    alert(test); 
} 
testA(true); // 'OK' 
testB(true); // 'OK' 
testA(false); // null 
testB(false); // undefined, no error 

En valor global de mi prueba caso específico ('no!') Ni se espera ni necesaria.

+0

comparativas que, http: // jsperf. com/undefined-variables –

Respuesta

6

No puede declarar las variables de forma condicional.

¿Por qué?

El proceso de instanciación variable aparece antes la ejecución de código real, en el momento en que se ejecuta la función, esas variables se ya vinculado al ámbito local, por ejemplo:

function foo() { 
    if (false) { 
    var test = 'foo'; // never executed 
    } 
    return test; 
} 
foo(); // undefined 

cuando la función se a punto de ser ejecutado, los identificadores de los parámetros formales, los identificadores de las declaraciones de variables y los identificadores de las declaraciones de funciones dentro del cuerpo de la función están vinculados al entorno de variables locales.

Las variables se inicializan con undefined.

También, identificadores en el local de alcance sombra los otros con el mismo nombre, superior en la cadena de ámbito, por ejemplo:

var test = 'global'; 
function bar() { 
    alert(test); // undefined, not "global", the local variable already declared 
    var test = 'xxx'; 
} 
bar(); 

Si la variable test no fueron declarados en cualquier lugar, un ReferenceError serán tirado:

function foo() { 
    return test; 
} 

try { 
    foo(); // ReferenceError!! 
} catch (e) { 
    alert(e); 
} 

Esa es una de las razones de por qué, por ejemplo, sólo se recomienda JSLint one var statement en la parte superior de las funciones, porque por ejemplo, t él primer fragmento, en realidad se parecen a esto cuando es ejecutado:

function foo() { 
    var test; // var statement was "hoisted" 
    if (false) { 
    test = 'foo'; // never executed 
    } 
    return test; 
} 
foo(); // undefined 

Otra razón es porque los bloques no introducen un nuevo ámbito léxico, sólo funciona lo hacen, por lo que tener una declaración var dentro de un aspecto que podría hacer pensar que la vida de la variable está restringida a ese bloque solamente, pero ese no es el caso.

declaraciones de funciones anidadas tendrán un comportamiento similar de hoisting, que se declararán antes de la ejecución de código, pero se inicializan en ese momento también:

function foo() { 
    return typeof bar; 
    // unreachable code: 
    function bar() { 
    //.. 
    } 
} 
foo(); // "function" 
+1

Solo para exponer sobre esto ... Creo que lo que CMS (y JSLint) significan con "una sentencia var por función" es, independientemente de la cantidad de variables declaradas, declararlas todas en una sola línea en la parte superior con comas para separar ellos de esta manera: 'var test = 'test', value = 'value', run = 'around';' – treeface

+0

@treeface, sí, el segundo motivo por el que JSLint recomienda esto es que las sentencias 'Block' (como' { } 'bloques usados ​​después de declaraciones de iteración, instrucción 'if', etc.) no introducen un nuevo alcance, solo las funciones introducen un nuevo entorno léxico donde las variables pueden declararse. Entonces, tener una declaración 'var' en la parte superior de la función, puede evitar confusiones. – CMS

+0

Gracias. Agregué algo a la pregunta para aclarar que no esperaba declarar las variables condicionalmente, ya lo había aprendido. Mi pregunta era más acerca de lo que dijo sobre JSLint (lo comprobaré, mientras tanto), ¿el rendimiento es un factor para esa recomendación? –

4

Si la variable no necesita manipular por cualquier otra función, mantener la variable dentro de una función con var foo;.

De lo contrario, si es necesario acceder y leer en varios ámbitos, manténgalo fuera. Pero recuerda que cuando lo mantienes afuera, se vuelve global. Es decir, a menos que se coloca todo en una función de auto ejecución, que es la mejor manera:

(function() { 
    var president='bush'; 

    function blah() { 
    president='reagan'; 
    } 

    function meh() { 
    president= 'carter'; 
    } 

    document.getElementById('reagan').onclick=blah; 
    document.getElementById('carter').onclick=meh; 


})(); 

alert(president) // undefined 

Lo anterior es perfecto para una variable visitada por funciones definidas dentro de ese ámbito. Como hay 2 elementos en los que hago clic para establecer el presidente, tiene sentido definirlo fuera de ambas funciones porque establecen la misma variable.

Por lo tanto, si no tiene varias funciones cambiando la misma variable, manténgalas localmente en la función.

+0

Entiendo su punto, lo descubrí al depurar en una situación en la que quería usar el valor global de prueba ('SNAP!'). Pero, en este caso, quiero que sea nulo y no tenga ningún valor global. Me preguntaba si se consideraba una buena práctica. Gracias. –

+0

alert (president) arrojaría un error –

+0

@Juan Mendes - right. Eso es para demostración. –

2

¿El testB es una mejor programación? No, porque da un resultado inesperado de "indefinido" (al menos, eso me sorprendió) y es difícil de leer.

En general, las variables deben estar limitadas al alcance que las requiere, de modo que si la variable "prueba" no es necesaria fuera de la función, debe declararse local. Para evitar confusiones, declarar la variable antes de usarla:

function testC(boolean) { 
    var test; 
    if (boolean) { 
     test = "OK"; 
    } 
    else { 
     test = null; 
    } 
    alert(test); 
} 

A menos que realmente desea cambiar la versión de alcance global de "prueba", en cuyo caso no utilizan la palabra clave var dentro de la función.

Si alguna vez se encuentra utilizando el mismo nombre para una variable local y una variable global, puede considerar renombrar uno de ellos.

+0

Bueno, ahora que lo espero y lo quiero (no necesito 'SNAP!'), ¿Por qué no está bien? ? ¿Actuación? ¿O simplemente legibilidad? –

+1

Solo legibilidad y facilidad de mantenimiento (que son casi sinónimos). Si tiene una variable global cuando no la necesita, un día la sobrescribirá accidentalmente en otro lugar y pasará un día averiguando por qué se rompió todo. –

+0

O más bien definidos, los globales agregan un acoplamiento hermético entre su módulo y el entorno. Si necesita reutilizar su módulo, tendrá que perseguir esos elementos globales y replicarlos en un entorno separado. Si necesita compartir una variable entre un par de funciones, la función de auto llamada es un gran patrón –

Cuestiones relacionadas