2010-08-13 21 views
5

Wziąłem to z Google Code Playground http://code.google.com/apis/ajax/playground/jak uzyskać dostęp do zmiennych w zamknięciach, jeśli istnieją zmienne lokalne o tej samej nazwie?

/*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); 

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

jej wszystko ok, ale jeśli mam zmiennej lokalnej w funkcji wewnętrznej o tej samej nazwie jako zmienna w funkcji zewnętrznej następnie jak uzyskać dostęp do tej zmiennej?

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

Dlaczego nie zmienić nazwy jednego z nich? – kennytm

+0

Wstawiłem linię var ss = someString; wewnątrz funkcji wewnętrznej. Wtedy, gdy próbowałem uzyskać dostęp do ss, wrócił niezdefiniowany – Sriram

+0

Bardzo podobny/duplikat? pytanie: http://stackoverflow.com/questions/1484143/scope-chain-in-javascript –

Odpowiedz

8

Nie można, ponieważ zmienna zewnętrznego zakresu jest zacieniona przez jedną z funkcji wewnętrznych.

Łańcuch zakres na innerFunction wygląda mniej więcej tak:

 

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

* Denotes a resolvable identifier from the scope of innerFunction. 

Każda funkcja posiada własną zmienna obiektu, gdzie identyfikatory deklaracje funkcji, deklaracje zmiennych i funkcji parametrów formalnych żyć, jak nieruchomości.

Obiekty te nie są bezpośrednio dostępne przez kod, łańcuch zasięgu jest tworzony przez wszystkie te powiązane obiekty.

Gdy identyfikator ma numer resolved, wyszukiwanie rozpoczyna się w łańcuchu zasięgu, szukając jego pierwszego pojawienia się, dopóki obiekt globalny nie zostanie osiągnięty, jeśli identyfikator nie zostanie znaleziony, zostanie zgłoszony ReferenceError.

Daj spojrzeć w następujących artykułach:

+0

Czy jest do tego jakieś zadanie? – Sriram

+0

@Sriram - Zmień nazwy zmiennych lub podaj jako zmienną zewnętrzną zmienną. –

+0

@CMS - Twój rysunek się zepsuł :( –

0

Spróbuj z this.varname, aby odwołać się do tego w zamknięciu.

this.someString w twoim przykładzie.

+1

Znaczenie zmiennej 'this' zależy od tego jak wewnętrzny jest wywoływany, więc to zadziała tylko wtedy, gdy funkcja zawiera zakres zamknięcia jest kontekstem, z którego funkcja wewnętrzna została nazwana jako metoda. Jeśli przekażesz tę funkcję do jakiegoś innego obiektu, a następnie wywołasz ją, nawet jeśli link do zamknięcia jest nadal tam, to 'this' nie wskazuje na to. – thomasrutter

+0

Prawda. Zdałem sobie z tego sprawę i miałem zamiar usunąć własną odpowiedź, ale twoje wyjaśnienie sprawiło, że warto było zostać. :) –

+0

Czy możesz wyjaśnić to trochę więcej? Nie dostałem jeszcze "tego" materiału! – Sriram

0

Mogłeś

  • prostu uniknąć tworzenia dowolnej zmiennej lokalnej o tej samej nazwie, lub
  • zrobić lokalną kopię tego zamknięcia zmiennej przed deklarowania zmiennej lokalnej o tej samej nazwie (jeśli naprawdę chcesz lokalną zmienną o tej samej nazwie)

(miał obejście ale usunięto go po wskazywano, że nie będzie faktycznie działać)

+0

Nigdy nie wywołujesz 'innerfunc()' tylko zewnętrznego. –

+1

'copyofmyvar' będzie zawsze' undefined', proces Variable Instantiation odbywa się * przed * faktycznym wykonaniem funkcji, zmienne napotkane w zasięgu zostają zainicjowane za pomocą 'undefined' i dzieje się to z' myvar' zdefiniowanym w wewnętrznym zasięgu, jest dodawany do obiektu Variable Object i inicjowany przez 'undefined', później funkcja wykonuje i sprawia, że ​​przypisania i do tego czasu' myvar' z zewnętrznego zakresu są już zacienione. – CMS

+0

http://jsfiddle.net/tjYz5/ –

1

lokalne zmienne zamknięcia „cień” zmiennych o tej samej nazwie z funkcji zewnętrznej, więc tak:

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

will alert Hello.

Jedynym sposobem, aby obejść to do zmiany nazwy zmiennych, lub przechodzą w zmiennej chcesz pracować z:

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

Will alert Hai!

Aby dowiedzieć się o łańcuchu zasięgu, 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);

Powiązane problemy