2012-06-21 3 views
5

Я пытаюсь понять правила области видимости JavaScript. То, что я прочитал в учебниках и документации, путается.Контекст JavaScript и контекст выполнения

Мне кажется, что JavaScript - это статически (или лексически) язык с областью - при попытке привязать имя переменной к переменной (определению) используется лексическая структура кода.

Контекст исполнения похоже на стек стека в стеке вызовов. Каждый контекст выполнения имеет переменный объект, на котором определены все локальные переменные (связанной функции). Эти переменные объекты связаны между собой, чтобы обеспечить «цепочку областей видимости» из объекта переменной в верхней части стека объекту переменной в нижней части стека (объект окна). Эта цепочка областей поиска выполняется сверху вниз, привязывая имена переменных к переменным. Это очень похоже на языки с фиксированным охватом, такие как C/C++/Java.

Существует, по-видимому, одно важное отличие по отношению к C/C++/Java - возможно получить доступ к переменной, определенной в функции, стек стека которой больше не находится в стеке вызовов, как показано в примере ниже:

var color = "red"; 
var printColor; 

function changeColor() { 
    var color = "green"; 

    printColor = function(msg) { 
     alert(msg + color); 
    } 
    printColor("in changeColor context, color = "); // "green" 
} 

changeColor(); 

// stack frame for "changeColor" no longer on stack 
// but we can access the value of the variable color defined in that function 

printColor("in global context, color = "); // "green" 

Есть ли у меня это право? Есть ли другие проблемы, о которых я должен знать?

Заранее спасибо

+4

Очень подробный пост, посвященный HN сегодня, который затрагивает это: [Что такое контекст выполнения и стек в JavaScript?] (Http://davidshariff.com/blog/what-is-the-execution-context-in- javascript /) –

+2

Это называется * замыканием *. Функция, которую вы назначили 'printColor', имеет доступ ко всем переменным, определенным в' changeColor', даже после завершения функции. Я не знаю, как это происходит в C. –

+0

@FelixKling почти. однако changeColor также определяется в глобальном масштабе, поэтому его область никогда не будет собрана мусором. – webduvet

ответ

2

Это действительно большая разница между C/C++ и JavaScript: JavaScript является ссылкой подсчета, сборщик мусором языка, это означает, что объекты могут быть утилизированы двигателем, когда они больше нет ссылок на них. Функция, которую вы назначаете printColor, не находится в стеке, так как она будет на C или C++; он распределяется динамически, а затем назначается переменной за пределами текущей области. Таким образом, когда возвращает поток управлени от changeColor, анонимная функция все еще имеет счетчик ссылок Так как наружный printColor относится к нему, и, таким образом, это использовать от внешнего объема.

Итак, ваш пример не столько вопроса обзорного - это ясно, что вы объявляете printColorвне функции объема changeColor. Когда вы определяете changeColor, это closes upvalue printColor в новый диапазон функций, что делает его доступным. Как Combat сказал, если добавить var ко второму, внутреннему определению из printColor, это будет shadow первого printColor вы объявили, и он не будет доступен за пределами этой функции блока.

Что касается других вопросов, о которых нужно знать, да, их немало, но см. Мой комментарий на ваш исходный пост для хорошего старта.

+0

Увы, я, возможно, неправильно понял вопрос (w.r.t. «переменная цвета»), но я думаю, что то, что я написал, все еще содержит воду. –

+0

Когда вы говорите, что printColor не находится в стеке, я предполагаю, что вы имеете в виду объект, представляющий printColor. Когда вызывается printColor, его кадр контекста/стека выполнения помещается в стек. Или я понял? – asterix

0

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

Анонимная функция определена в локальной области функции changeColor вместо глобальной области.Следовательно, когда он выполняется снова, он печатает зеленый цвет, который указан в локальной области функции changeColor.

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