Первый. Переменные. Оператор var и магия областей определения переменных

Суббота, 30 января 2010 года, 19:50. Напечатано в категориях JavaScript, Кодекс, Оптимизация12

Здравствуйте ;)

С сегодняшнего дня я начинаю вести цикл статей об оптимизации в JavaScript!
В цикле статей я постараюсь рассмотреть все аспекты и принципы оптимизации, разные трюки и наилучшие варианты кода для той или иной ситуации, а также буду объяснять, “Почему так?”. Буду стараться рассматривать ситуации от макро-оптимизации до мини- и микро-оптимизации :)

Это самая первая статья. Сегодня я расcкажу вам о переменных в JavaScript.

Переменные в JavaScript назначаются с помощью оператора var.

var name1 = 55;
var name2 = 'строка';
var name3 = function( a ){
  alert( 'Передали: ' + a );
};
var name4 = new Object();
var name5 = /^регулярное выражение$/g;
// Используем переменную
alert( 'Число ' + name1 );

Всё, что создавалось не с помощью оператора var – не переменная.

var name6 = 'Строка в переменной';
name7 = 'Строка в свойстве глобального объекта - не переменная';
window.name8 = 'Назначение name7 аналогично такой записи';
this.name9 = 'Или такой';

И самое первое правло в цикле статей :)

Правило 1
С помощью оператора var можно объявить несколько переменных используя запятую после значения переменной.
Синтаксис:

var name1 = value1, name2 = value2, name3 = value3...

Следуя ему мы уже можем ускорить свой код:

var
  name1 = 55,
  name2 = 'строка',
  name3 = function( a ){
    alert( 'Передали: ' + a );
  },
  name4 = new Object(),
  name5 = /^регулярное выражение$/g;
// Используем переменную
alert( 'Число ' + name1 );

Интерпретатор единожды увидев оператор var создаёт переменные по циклу, идущие через запятую.
Выходит, намного выгоднее использовать один оператор var и перечислить все переменные!
Далее советую очень строго придерживаться этого правила, оно вам поможет в будущем ;)

Далее поговорим подробнее об определении переменных… в функциях!

Правило 2
Объявляя переменную в функции, мы прикрепляем её к этой функции, а точнее к её области видимости переменных!
Область видимости переменной – текущая функция. Если переменная объявлена вне функции, то ее область видимости – глобальный объект window.

То есть:

var name1 = 55;
alert( name1 );

function name2(){
  var name1 = 88;
  alert( name1 );
};
name2();

alert( name1 );

Здесь переменная, объявленная внутри функции становится видна только в области видимости переменных данной функции, а также ещё во вложенных функциях в эту функцию(благодаря замыканиям, о которых позже):

var name1 = 55;
alert( name1 );

function name2(){
  var
    name1 = 88,

    fn = function(){
      alert( name1 );
    };

  fn();

};
name2();

alert( name1 );

Это значит, что можно полностью использовать переменные, назначенные в функциях, которые породили нашу текущую функцию:

var name1 = 55;
alert( name1 );

function name2(){
  // без var
  name1 = 88;
  alert( name1 );
};
name2();

alert( name1 );

Такой подход очень удобен! Но немного теории: когда в нашей функции name2 идёт обращение к переменной name1, наша функция ищет name1 в своей области видимости переменных. Если она не обнаружила переменную с таким именем, то функция просматривает области видимости переменных в функциях, которые породили нашу функцию(точнее являются её обёртками). Если она нашла переменную с таким именем, то начинает полноценно управлять её(в нашем случае – это назначение переменной name1 числа 88). Если же функция не нашла таких переменных в этом процессе – она производит поиск в области видимости объекта window.

Отсюда отчётливо вытекает третье правило микро-оптимизации:

Правило 3
Чтобы предотвратить поиск функцией переменных в областях определения переменных “функций-обёрток”, нужно всего лишь назначить в этой функции переменную, значение которой будет либо равно нужной переменной, либо будет являться ссылкой на нужную переменную.

Сразу пример для большего понимания:

var name1 = new Object();
name1.fn1 = function( number ){
  return number * number;
};

function name2(){
  // Создаём ссылку на объект
  var obj1 = name1;
  for( var i = 1; i < 10; i++ )
    document.write(
      i + ' умножить на ' + i
      + ' равно ' + obj1.fn1( i )
      + '<br>'
    );
};
name2();

Или же сохраняем имя объекта – передаём его в функцию:

var name1 = new Object();
name1.fn1 = function( number ){
  return number * number;
};

function name2( name1 /*Ссылка создаётся автоматически*/ ){
  for( var i = 10; i < 21; i++ )
    document.write(
      i + ' умножить на ' + i
      + ' равно ' + name1.fn1( i )
      + '<br>'
    );
};
name2( name1 );

Пример реального использования? Да пожалуйста :)
Библиотека jQuery 1.4:

(function( window ){
  // Здесь в нашем коде спокойно используем window
  // И знаем то, что он вызывается довольно быстро ;)
})( window );

Спасибо за внимание и удачи ;)
С уважением, Regent :)



Комментарии(12)

bm пишет в субботу, 30.01.2010 в 21:34 Ответить
Отличная статья. С нетерпением жду продолжения.
Спасибо за доходчивую и интересную подачу материала.
Да и весь блог vl.vg необычный. Автор молодец, при возможности пропиарю.
Думаю теперь я смогу полюбить JavaScript.
Regent пишет в субботу, 30.01.2010 в 22:09 Ответить
@bm, благодарю =)
Дмитрий пишет в субботу, 30.01.2010 в 23:49 Ответить
Пример с document.write (да еще в цикле) не совсем уместен в статье об оптимизации))
Еще, не знаю, в тему или нет (свойство объекта это почти тоже, что переменная) - чем больше вложенность свойств в объекте, тем медленне скорость доступа к объекту, т.е.:
window.myobj.myvar.anothervar.target = 0;
Regent пишет в воскресенье, 31.01.2010 в 9:47 Ответить
@Дмитрий, согласен, но эта статья совсем не об этом
Эту тему планирую рассмотреть в статье про кеширование. Вот там и буду писать, почему так лучше
for( var i = 10, code =''; i < 21; i++ ){
  code += i + ' умножить на ' + i
    + ' равно ' + name1.fn1( i )
    + '<br>';
};
document.write( code );


Чтобы совсем не запутаться, пока будем называть всё то, что создано с помощью оператора var - переменные.

window.myobj.myvar.anothervar.target = 0;

Спасибо, тоже собираюсь рассмотреть эту ситуацию в статье о кешировании!

Спасибо за комментарий =)
Master Nayjest пишет в понедельник, 01.02.2010 в 4:20 Ответить
Как это "var – не переменная". Почему это вдруг поле объекта не является переменной? (ò_ó)

p.s.: Жабаскриптовый беспредел с подсветкой в этом блоге очень доставляет (>_<")
Regent пишет в понедельник, 01.02.2010 в 9:26 Ответить
@Master Nayjest, поле объекта - это видимо свойство объекта? Ну тогда переменная и свойство объекта - это две абсолютно разные вещи - на них действуют "разные законы гравитации".

Про беспредел не понял Вы имели ввиду codeEvaluator?
Lemurian пишет в понедельник, 01.02.2010 в 23:17 Ответить
Вот подумалось, стОит ещё посоветовать не перегружать глобальную область видимости переменными без причины.
Конечно, из Правила 3 это и так можно понять, но замедление поиска переменных - не единственный недостаток глобальной области видимости.
Regent пишет в понедельник, 01.02.2010 в 23:52 Ответить
@Lemurian, да, вы правы
Мы об этом говорили 10 января в самой первой статье в рубрики Оптимизации =)
Статья называется "Анонимная функция – необузданная мощь JavaScript!" и находится по адресу http://vl.vg/10.01.2010/anonim-function/
Там даже в конце есть
Мы защитили объект window от внеземных вторжений!

Lemurian пишет во вторник, 02.02.2010 в 1:01 Ответить
@Regent, прошу прощения, не заметил
h1 пишет в среду, 03.02.2010 в 1:48 Ответить
отличная идея для цикла статей!

если не ошибаюсь, то в данном случае:
function name2(){
....};

точка с запятой не нужна.
А в случае var name2 = function(){...}; нужна, т.к. это определение переменной.

В примере с ускорением поиска переменных можно создать ссылку не на объект а прямо на вызываемую функцию, это еще несколько ускорит работу, т.к. обращение к полю/методу объекта - тоже занимает время.

Спасибо за статью. Весьма познавательно
Regent пишет в среду, 03.02.2010 в 8:40 Ответить
@h1, да, там точка с запятой совершенно не нужна, но во всём виноват мой синтаксис

На счёт функции вы совершенно правы, но это уже будет относится к будущей теме кеширования
TRAHOMOTO пишет во вторник, 09.02.2010 в 23:34 Ответить
Спасибо! Почерпнул новые знания
Уведомлять меня о новых комментариях по почте
Для корректной работы отправки комментариев необходимо включить JavaScript
Либо скачать новый нормальный браузер