Область видимости переменной в Javascript (variable scope) – ликбез 22 декабря 09
Для меня одним из самых проблемных мест Javascript было управление переменными. Излагаю простым русским языком.
Области видимости переменных
Переменные в Javascript бывают глобальными и локальными. Глобальная переменная доступна везде, локальная – только в текущей области видимости.
Технически, глобальные переменные – всего лишь свойства объекта window, поскольку весь код выполняется в его контексте.
<script> alert(location); // сообщит window.location </script>
Из этого следует, что глобальные переменные могут затирать свойства window (я уже молчу о том, что они зло, нарушают инкапсуляцию и все такое).
Объявление переменных
При присвоении значения неопределенной локальной переменной используется или создается глобальная переменная.
function foo() { a = 2; b = 3; return a+b; } alert(a); // undefined a = 'очень важное значение'; alert(a); // очень важное значение foo(); alert(a); // 2
Таким образом можно легко затереть лишнего. По-моему такое поведение абсолютно нелогично, но, что ж, это не самое странное место яваскрипта. В любом случае неявного определения переменных стоит избегать.
Явно объявлять переменные можно и нужно ключевым словом var.
var a = 2;
Такая строка всегда создает новую локальную переменную. Если объявление происходит вне функций, то она будет глобальной, что вполне логично.
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 можно определять функции внутри функций, а использовать их потом где угодно. Ну да, если посмотреть, точно то же самое можно делать в Ruby, и, наверное, во многих других языках тоже.
Переменные при этом передаются очень просто: если на момент определения функции переменная существовала, то она будет существовать и внутри функции. Откуда бы ее не вызывали.
function alertOnTimeout(message, timeout) { return setTimeout(function() { // message будет доступен в безымянной функции, переданной таймауту alert(message); }, timeout); }
Передача кода по старинке – строкой, которая прогоняется через eval() – не попадает под это правило, код исполняется в той области видимости, где и определен.
Поскольку объекты в Javascript – это тоже типа функции, то свойство объекта определяется точно так же, как и переменная.
function myObject() { var property = 0; // Cамо собой, property будет доступно только внутри объекта. }
А еще в Javascript область видимости переменной ограничивается только функциями, а не блоками типа if (привет, Паскаль). Потому удобнее всего объявлять переменные в начале функции.
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 - это родительский объект }); }

Подписаться на RSS

Комментарии
Спасибо за статью, я наконец-то разложил по полочкам все по поводу областей видимости в JavaScript.
А можно ли как-то из функции объявить глобальную переменную, кроме как просто начать ее использовать? )
Хороший вопрос, заставил меня немного переделать статью. Суть в том, что глобальные переменнные принадлежат объекту window и с ними можно работать через разыменование.
Короткий ответ: window.global_variable = ‘variable value’;
я думал, что все уже давно знают об этом =)
У меня вопрос, как получать значения переменных, объявленных в других функциях? Например:
function f1(){
var a =»1″;
}
function f2(){
alert (a);
}
Определить переменную в области видимости, доступной из обеих функций.
То есть:
var a=»";
function f1(){
var a =»1″;
}
function f2(){
alert (a);
}
?