2010-08-13 2 views
5

Я принял это от Google Code Playground http://code.google.com/apis/ajax/playground/Как получить доступ к переменным в закрытии, если есть локальные переменные с тем же именем?

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

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

Ее все в порядке, но если у меня есть локальная переменная во внутренней функции с тем же именем переменной во внешней функции, то, как получить доступ к этой переменной?

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

Почему бы не переименовать один из них? – kennytm

+0

Я вставил строку var ss = someString; внутри внутренней функции. Тогда, когда я пытался получить доступ к ss, он возвращался undefined – Sriram

+0

Очень похожее/дублирующее? Вопрос: http://stackoverflow.com/questions/1484143/scope-chain-in-javascript –

ответ

8

Вы не можете, потому что переменная внешней области затенена тем, что находится на вашей внутренней функции.

Объем цепи на innerFunction выглядит примерно так:

 

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

* Denotes a resolvable identifier from the scope of innerFunction. 

Каждая функция имеет свою собственную переменную Object, где живут идентификаторы функций декларациях, описание переменных и функций формальных параметров, а свойства.

Эти объекты непосредственно не доступны по коду, цепочка областей видимости образована всеми этими цепными объектами.

Когда идентификатор равен resolved, поиск продолжается в цепочке областей видимости, ища первый вид его, пока не будет достигнут глобальный объект, если идентификатор не найден, выбрано значение ReferenceError.

Дайте взглянуть на следующие статьи:

+0

Есть ли работа для этого? – Sriram

+0

@Sriram - изменить имена переменных или передать внешнюю переменную в качестве аргумента. –

+0

@ CMS - Ваш рисунок сломался :( –

0

Попробуйте с этим.varname обратиться к тому, который находится в закрытии.

это.Сохранить место в вашем примере.

+1

Значение переменной 'this' зависит от того, как вызвано внутреннее, поэтому это будет работать, только если функция, содержащая область закрытия является контекстом, из которого внутренняя функция была вызвана как метод. Если вы передадите эту функцию другому объекту и затем вызовите его, хотя ссылка на закрытие все еще существует, 'this' не укажет на нее. – thomasrutter

+0

Правда. Я понял это и собирался удалить свой собственный ответ, но ваше объяснение заставил его остановиться. :) –

+0

Можете ли вы объяснить это немного больше? Я еще не получил «этот» материал! – Sriram

0

Вы можете

  • просто избежать создания каких-либо локальную переменную с тем же именем, или
  • сделать локальную копию этого закрытия переменной перед тем объявить локальную переменную с тем же именем (если вы действительно хотите локальную переменную с тем же именем)

(имел обходной путь, но удалить его после того, как было отмечено, что оно не будет реально работать)

+0

Вы никогда не называете 'innerfunc()' только внешним. –

+1

'copyofmyvar' будет всегда' undefined', процесс Variable Instantiation происходит * перед * фактическим выполнением функции, переменные, встречающиеся в области видимости, инициализируются с помощью 'undefined', и это происходит с' myvar', определенным во внутренней области, добавляется в объект переменной и инициализируется с помощью 'undefined', позже функция выполняет и выполняет присвоения, и к этому времени« myvar »из внешней области уже затенен. – CMS

+0

http://jsfiddle.net/tjYz5/ –

1

локальные переменные закрывающего «тени» переменных одного и того же имени из внешней функции, так что:

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

will alert Hello.

Единственный способ обойти это переименовать переменные, или передать в переменной, которую вы хотите работать с:

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

Will alert Hai!

Чтобы узнать о цепочке областей видимости, 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);

Смежные вопросы