4. Основы JavaScript


4.11. Инструкции

ЕСМА-262 включает несколько инструкций, называемых также управляющими инструкциями, которые составляют основную часть синтаксиса ECMAScript и обычно решают специфическую задачу с помощью одного или нескольких ключевых слов. Сложность инструкций варьируется в широких пределах: от тривиального выхода из функции до блоков многократно выполняемых команд.

Инструкция if.

Инструкция if часто используется почти во всех языках программирования. Она имеет следующий синтаксис:

if (условие) инструкция1 else инструкция2

Условие может быть любым выражением. Оно даже может не относиться к логическому типу, потому что ECMAScript автоматически преобразует результат выражения в логическое значение, вызывая для него функцию boolean (). Если условие эквивалентно true, выполняется инструкция1, в противном случае – инструкция2. Любая из инструкций может быть одной строкой или блоком кода (группой строк в фигурных скобках), например:

if (i > 25)
alert ("Больше 25"); // однострочная инструкция
else {
alert ("Меньши или равно 2"); // блочная инструкция
}

Рекомендуется всегда использовать блочные инструкции, даже если нужно выполнить всего одну строку кода. Это ясно показывает, что должно быть выполнено в каждом случае.

Инструкции if можно сцеплять друг с другом:

if (условие1) инструкция1 else if (условие2) инструкция2 else инструкция3

Пример:

if (i > 25) {
alent ("Больше 25");
}
else if (i < 0) {
alert ("Меньше 0");
}
else {
alert ("Между 0 и 25 включительно");
}
Инструкция do-while.

Инструкция do-while создает цикл с постусловием, в котором условие выхода из цикла проверяется только после выполнения кода внутри него. Тело цикла выполняется как минимум один раз перед оценкой выражения. Вот синтаксис цикла:

do {
инструкция
} while (выражение);

Пример:

var i = 0;
do {
i += 2;
} while (i < 10);

Этот цикл продолжается, пока переменная i меньше 10. Она равна 0 в начале цикла и увеличивается на 2 на каждой итерации.

Циклы с постусловием чаще всего используются, если тело цикла должно быть выполнено хотя бы один раз.

Инструкция while.

Инструкция while создает цикл с предусловием. Это означает, что условие выхода из цикла проверяется перед выполнением кода внутри него. Возможно, что тело цикла не будет выполнено ни разу. Синтаксис этого цикла таков:

while (выражение) инструкция

Пример:

var i = 0;
while (i < 10) {
i += 2;
}

Переменная i равна 0 перед началом цикла и увеличивается на 2 на каждой итерации. Пока она меньше 10, цикл продолжается.

Инструкция for.

Инструкция for – это вариант цикла с предусловием, позволяющий инициализировать переменную перед началом цикла и указать код, выполняемый после цикла. Она имеет следующий синтаксис:

for (инициализация; выражение; выражение после цикла) инструкция

Пример:

var count = 10;
for (var i=0; i < count; i++) {
alert (i);
}

В этом фрагменте определяется переменная i с нулевым значением. Цикл for начинается, только если результатом условного выражения (i < count) является значение true, то есть тело цикла может быть не выполнено ни разу. Если тело цикла выполняется, вслед за ним в выражении после цикла увеличивается значение i. Этот цикл for эквивалентен следующему:

var count = 10;
var i = 0;
while (i < count) {
alert (i);
i++;

}

С помощью инструкции for нельзя сделать ничего такого, что невозможно было бы выполнить в цикле while, она просто группирует связанный с циклом код в одном месте.

Использовать ключевое слово var в разделе инициализации цикла for не требуется. Это можно сделать и вне цикла:

var count = 10;
var i;
for (i=0; i < count; i++) {
alert (i);
}
Инструкция for-in.

Инструкция for-in используется для перебора свойств объектов и имеет следующий синтаксис:

for (свойство in выражение) инструкция

Пример:

for (var propName in window) {
document.write (propName);
}

Здесь инструкция for-in используется для вывода из объектной модели браузера на экран всех свойств объекта windows. При каждой итерации цикла переменной propName присваивается имя очередного свойства. Это продолжается, пока не будут перебраны все доступные свойства. Как и в цикле for, оператор var в управляющем выражении здесь не обязателен, но рекомендуется использовать его, чтобы переменная была локальной.

Свойства объектов в ECMAScript не упорядочены, поэтому порядок возврата их имен в цикле for-in предсказать нельзя. Все перечислимые свойства будут возвращены, но порядок их вывода может зависеть от браузера.

Если переменная, представляющая перебираемый объект, равна null или undefined, инструкция for-in генерирует ошибку, а в ECMAScript 5 вместо этого тело цикла просто не выполняется. Для обеспечения совместимости рекомендуется проверять значение объекта перед циклом for-in на предмет того, не равно ли оно null или undefined.

Инструкции break и continue.

Инструкции break и continue обеспечивают более точный контроль над выполнением кода в цикле. Инструкция break немедленно завершает цикл, передавая управление следующей инструкции после цикла, a continue завершает только текущую итерацию цикла, начиная новую. Рассмотрим пример:

var num = 0;
for (var i=1; i < 10; i++) {
if (i % 5 == 0) {
break;
}
num++;

}
alert (num); // Результат равен 4

В цикле for переменная i увеличивается с 1 до 10. В теле цикла инструкция if с помощью оператора деления по модулю проверяет, делится ли значение i без остатка на 5. Если да, выполняется инструкция break и цикл завершается. Переменная num подсчитывает количество итераций цикла. После break выводится оповещение со значением 4. Цикл выполняется 4 раза потому, что когда i равно 5, инструкция break завершает цикл до очередного увеличения значения num. Если изменить break на continue, получится другой результат:

var num = 0;
for (var i=1; i < 10; i++) {
if (i % 5 == 0) {
continue;
}
num++;

}
alert(num); // Результат равен 8

В этот раз итоговое количество итераций равно 8. Когда i достигает значения 5, итерация цикла завершается до увеличения переменной num, но цикл продолжается со следующей итерации со значением i, равным 6. Затем цикл выполняется до естественного завершения при значении i, равном 10. Окончательное значение num равно 8, а не 9, потому что одна операция инкремента пропускается из-за инструкции continue.

И break, и continue можно использовать вместе с помеченными инструкциями для возврата к конкретному месту в коде. Обычно это делается во вложенных циклах, например:

var num = 0;
outermost:
for (var i=0; i < 10; i++) {
for (var j=0; j < 10; j++) {
if (i == 5 && j == 5) {
break outermost;
}
num++;

}

}
alert (num); // Результат равен 55

В этом примере для первой инструкции for добавлена метка outermost. Каждый цикл включает 10 итераций, то есть инструкция num++ предположительно должна быть выполнена 100 раз, после чего переменная num должна быть равна 100. Инструкция break получает здесь в качестве аргумента метку для перехода, вследствие чего она завершает не только внутренний цикл for (с переменной j), но и внешний (с переменной i). Окончательное значение num равно 55, потому что циклы завершаются, когда i и j равны 5. Инструкция continue используется аналогично.

Инструкция with.

Инструкция with делает областью видимости кода конкретный объект. Вот ее синтаксис:

with (выражение) инструкция;

Инструкция with была создана ради удобства для тех случаев, когда имя одного объекта приходится вводить снова и снова, например:

var qs = location.search.substning(1);
var hostName = location.hostname;
var url = location.href;

Чтобы не указывать в каждой строке объект location, этот код можно переписать следующим образом:

with (location) {
var qs = search.substring(1);
var hostName = hostname;
var url = href;

}

В этой версии кода, где инструкция with используется с объектом location, каждая переменная внутри блока сначала считается локальной. Если выясняется, что она не является локальной, выполняется поиск свойства с тем же именем в объекте location. Если оно обнаруживается, переменная интерпретируется как свойство объекта location.

В строгом режиме инструкция with не поддерживается. Попытка использовать ее приведет к синтаксической ошибке.

Использование инструкции with в окончательном коде считается плохой практикой, потому что это снижает быстродействие и затрудняет отладку кода.

Инструкция switch.

С if тесно связана управляющая инструкция switch, также заимствованная из других языков. Синтаксис switch в ECMAScript напоминает аналоги в других С-подобных языках программирования:

switch (выражение) {
case значение: инструкция
break;
case значение: инструкция
break;
case значение: инструкция
break;
case значение: инструкция
break;
default: инструкция

}

Если выражение равно конкретному значению в блоке switch, выполняется соответствующая инструкция. Ключевое слово break вызывает выход из блока switch, в противном случае просто выполнялась бы следующая инструкция в списке. Ключевое слово default указывает код, который выполняется, если выражение не равно ни одному значению (по сути, оно аналогично else).

Инструкция switch избавляет от необходимости писать код вроде этого:

if (i == 25) {
alert ("25");
} else if (i == 35) {
alert ("35");
} else if (i == 45) {
alert ("45");
} else {
alert ("Другое значение");
}

Этот фрагмент эквивалентен следующему:

witch (i) {
case 25: alert ("25");
break;
case 35: alert ("35");
break;
case 45: alert ("45");
break;
default: alert ("Другое значение");

}

Лучше всегда добавлять слово break в конце каждого раздела case, чтобы управление не "проваливалось" в следующий раздел.