2010-08-13 16 views
5

Tomé esto desde Google Code juegos http://code.google.com/apis/ajax/playground/cómo acceder a variables en cierres si hay variables locales con el mismo nombre?

/*CLOSURE 
* When a function is defined in another function and it 
* has access to the outer function's context even after 
* the outer function returns 
* An important concept to learn in Javascript 
*/ 

function outerFunction(someNum) { 
    var someString = 'Hai!'; 
    var content = document.getElementById('content'); 
    function innerFunction() { 
    content.innerHTML = someNum + ': ' + someString; 
    content = null; // IE memory leak for DOM reference 
    } 
    innerFunction(); 
} 

outerFunction(1); 

/////////////////////// 

Su todo bien, pero si tengo una variable local en la función interior con el mismo nombre que una variable en la función externa a continuación, cómo acceder a esa variable?

function outerFunction(someNum) { 
    var someString = 'Hai!'; 
    var content = document.getElementById('content'); 
    function innerFunction() { 
    var someString='Hello'; 
    content.innerHTML = someNum + ': ' + someString; 
    content = null; // IE memory leak for DOM reference 
    } 
    innerFunction(); 
} 

outerFunction(1); 
+0

¿Por qué no cambiar el nombre de uno de ellos? – kennytm

+0

He insertado una línea var ss = someString; dentro de la función interna. Luego, cuando intenté acceder a ss, devolvió indefinido – Sriram

+0

¿Muy similar/duplicado? pregunta: http://stackoverflow.com/questions/1484143/scope-chain-in-javascript –

Respuesta

8

No se puede, porque la variable del alcance exterior está sombreada por la de su función interna.

La cadena de ámbito en el innerFunction se ve algo como esto:

 

    innerFunction      outerFunction    global object 
______________________   ________________________  _______________ 
|* someString = 'Hello'| <---- | someString = 'Hai!' | <---|* outerFunction| 
----------------------  |* content = [HTMLElement]|  | .....  | 
           |* someNum (argument)  |  --------------- 
           |* innerFunction   | 
           ------------------------- 

* Denotes a resolvable identifier from the scope of innerFunction. 

Cada función tiene su propia objeto variable, es donde viven los identificadores de las declaraciones de funciones, declaraciones de variables y la función parámetros formales, como propiedades.

Esos objetos no son directamente accesibles por código, la cadena de alcance está formada por todos los objetos encadenados.

Cuando un identificador es resolved, la búsqueda sube en la cadena de ámbito, en busca de la primera aparición de la misma, hasta que se alcanza el objeto global, si no se encuentra el identificador, un ReferenceError se lanza.

Dale un vistazo a los siguientes artículos:

+0

¿Hay una solución alternativa para esto? – Sriram

+0

@Sriram - Cambie los nombres de las variables o pase la variable externa como un argumento. –

+0

@CMS - Tu dibujo se rompió :( –

0

Pruebe con this.varname para hacer referencia al que está en el cierre.

this.someString en su ejemplo.

+1

El significado de la variable 'this' depende de cómo se llame al interno, por lo que esto solo funcionará si la función que contiene el alcance del cierre es el contexto desde el cual se llamó a la función interna como un método. Si pasa esa función a algún otro objeto y luego la llama, aunque el enlace al cierre todavía esté allí, el 'this' no lo señalará. – thomasrutter

+0

Es cierto. Me di cuenta de eso y estaba a punto de eliminar mi propia respuesta, pero tu explicación hizo que valiera la pena. :) –

+0

¿Puedes explicarlo un poco más? ¡Todavía no entendí el "esto"! – Sriram

0

Usted podría

  • simplemente evitar crear cualquier variable local con el mismo nombre, o
  • hacer una copia local de esa variable de cierre antes declarar la variable local con el mismo nombre (si realmente quieres una variable local del mismo nombre)

(tenía una solución, pero la retiró después de se señaló que no sería en realidad el trabajo)

+0

Nunca llamas 'innerfunc()' solo la externa. –

+1

'copyofmyvar' siempre será' undefined', el proceso de ejecución de variables tiene lugar * antes * de la ejecución de la función real, las variables encontradas en el alcance se inicializan con 'undefined' y esto sucede con el' myvar' definido en el alcance interno, se agrega al Objeto Variable y se inicializa con 'undefined', más tarde, la función se ejecuta y realiza las asignaciones y para ese momento' myvar' del ámbito externo ya está sombreado. – CMS

+0

http://jsfiddle.net/tjYz5/ –

1

las variables locales del cierre "sombra" las variables del mismo nombre de la función externa, por lo que este:

function outerFunction(s) { 
    var someString = 'Hai!'; 
    function innerFunction() { 
    var someString='Hello'; 
    alert(someString); 
    } 
    innerFunction(); 
} 
outerFunction(); 

will alert Hello.

La única manera de evitar que es para cambiar el nombre de las variables, o pasar en la variable que desea trabajar con:

function outerFunction(s) { 
    var someString = 'Hai!'; 
    function innerFunction(outer) { 
    var someString='Hello'; 
    alert(outer); 
    } 
    innerFunction(someString); 
} 
outerFunction();   

Will alert Hai!

para aprender acerca de la cadena de ámbito, take a look at this previous scope question.

0
function outerFunction(someNum) { 
var someString = 'Hai!'; 
var content = document.getElementById('content'); 
function innerFunction() { 
this.someString = 'Hello'; 
content.innerHTML = someNum + ': ' + someString; 
content = null; // IE memory leak for DOM reference 
} 
    innerFunction(); 

} outerFunction (1);

Cuestiones relacionadas