Область видимости переменной в Javascript (variable scope) - ликбез
December 22, 2009 , revised March 21, 2011 in JavaScriptДля меня одним из самых проблемных мест Javascript было управление переменными. Излагаю простым русским языком.
Обновление 21/03/2011: статья эта писалась давно, и ряд описанных в ней вещей оказались если не ошибочными, то по крайней мере неправильно описанными. Теперь ошибочных вещей стало меньше.
Вообще могу порекомендовать почитать раздел, посвященный области видимости, в Саду Javascript, да и весь Сад тоже.
Области видимости переменных
Область видимости переменной в Javascript ограничивается ближайшей функцией, в которой она определена.
Глобальных переменных (по крайней мере, в браузере) не бывает, поскольку все скрипты выполняются в контексте window
.
<script>
alert(location); // сообщит window.location
</script>
Объявление переменных
Без использования слова var
используется существующая переменная.
Если таковой нет, используется свойство объекта window
, то есть “как бы глобальная” переменная.
function foo() {
a = 2;
b = 3;
return a + b;
}
alert(a); // undefined
a = "очень важное значение";
alert(a); // очень важное значение
foo();
alert(a); // 2
Таким образом можно легко затереть лишнего. В любом случае определять переменные неявно в Javascript нельзя.
Явно объявлять переменные можно и нужно ключевым словом var
var a = 2;
Такая строка всегда создает новую локальную переменную. Если объявление происходит вне функций, создастся свойста объекта window
, что вполне логично.
function foo() {
var a = 2;
var b = 3;
return a + b;
}
alert(a); // undefined
var a = "очень важное значение";
alert(a); // очень важное значение
foo();
alert(a); // очень важное значение
Как объявить “глобальную” переменную из функции? Как обратиться к “глобальной” переменной, если есть локальная с таким же именем? Очень просто –
нужно обратиться к ней как к свойству window
:
function foo() {
var location = "location";
alert(location); // вернет 'location'
alert(window.location); // вернет window.location
window.a = "переменная из функции";
}
alert(a); // undefined
foo();
alert(a); // переменная из функции
Наследование области видимости
Функции в Javascript представляют собой замыкания. Что это значит? Что функции запоминают ту область видимости, в которой они были созданы.
Если на момент определения функции переменная существовала, то она будет существовать и внутри функции. Откуда бы ее не вызывали.
function alertOnTimeout(message, timeout) {
return setTimeout(function () {
// message будет доступен в безымянной функции, переданной таймауту
alert(message);
}, timeout);
}
Передача кода по старинке – строкой, которая прогоняется через eval()
– не попадает под это правило, код исполняется в той области видимости, где и определен.
Поскольку объекты в Javascript - это тоже типа функции, то свойство объекта определяется точно так же, как и переменная.
function myObject() {
var property = 0;
// Cамо собой, property будет доступно только внутри объекта.
}
this
А что this
? А то, что эта переменная автоматически появляется в методах объектов и затирает значение this
из предыдущей области видимости.
Решение простое – переприсваивать ее значение другой переменной.
$("div.with-links").click(function () {
var theDiv = this; //сохраняем значение this
$(this)
.find("a")
.click(function () {
alert($(this).attr("href")); // this - это ссылка
theDiv.remove(); // а theDiv - это все еще дивак
});
});
Отдельно замечу, что при оборачивании какой-то поведенческой логики в объект надо помнить, что в создаваемых DOM-событиях значение this
самого объекта теряется.
function myObject() {
var _this = this; // сохраняем ссылку на родительский объект
var linkRemoved = false;
$("a").click(function () {
$(this).remove(); // this - это объект ссылки
_this.linkRemoved = true; // _this - это родительский объект
});
}
Понравился пост? Купи мне кофе