Инструкция if создает ветвление в потоке исполнения программы. Многопози_ ционное ветвление можно реализовать посредством нескольких инструкций if, как показано в предыдущем разделе. Однако это не всегда наилучшее решение, особенно если все ветви зависят от значения одной переменной. В этом случае расточительно повторно проверять значение одной и той же переменной в не_ скольких инструкциях if.
Инструкция switch работает именно в такой ситуации и делает это более эффек_ тивно, чем повторяющиеся инструкции if. Инструкция switch в JavaScript очень похожа на инструкцию switch в Java или C. За инструкцией switch следует выражение и блок кода – почти так же, как в инструкции if:
104 Глава 6. Инструкции
switch(выражение) {
инструкции
}
Однако полный синтаксис инструкции switch более сложен, чем показано здесь. Различные места в блоке кода помечены ключевым словом case, за которым следу_ ет значение и символ двоеточия. Когда выполняется инструкция switch, она вы_ числяет значение выражения, а затем ищет метку case, соответствующую этому значению. Если метка найдена, исполняется блок кода, начиная с первой инст_ рукции, следующей за меткой case. Если метка case с соответствующим значением не найдена, исполнение начинается с первой инструкции, следующей за специаль_ ной меткой default:. Если метки default: нет, блок кода пропускается целиком.
Работу инструкции switch сложно объяснить на словах, поэтому приведем при_ мер. Следующая инструкция switch эквивалентна повторяющимся инструкциям if/else, показанным в предыдущем разделе:
switch(n) {
case 1: // Выполняется, если n == 1 // Исполняем блок кода 1.
break; // Здесь останавливаемся case 2: // Выполняется, если n == 2
// Исполняем блок кода 2. break; // Здесь останавливаемся
case 3: // Выполняется, если n == 3 // Исполняем блок кода 3.
break; // Здесь останавливаемся
default: // Если все остальное не подходит...
// Исполняем блок кода 4. break; // Здесь останавливаемся
}
Обратите внимание на ключевое слово break в конце каждого блока case. Инст_ рукция break, описываемая далее в этой главе, приводит к передаче управления в конец инструкции switch или цикла. Конструкции case в инструкции switch за_ дают только начальную точку исполняемого кода, но не задают никаких конеч_ ных точек. В случае отсутствия инструкций break инструкция switch начинает исполнение блока кода с метки case, соответствующей значению выражения, и продолжает исполнение до тех пор, пока не дойдет до конца блока. В редких случаях это полезно для написания кода, который переходит от одной метки case к следующей, но в 99 % случаев следует аккуратно завершать каждый блок case инструкцией break. (При использовании switch внутри функции можно помещать вместо break инструкцию return. Обе эти инструкции служат для завершения ра_ боты инструкции switch и предотвращения перехода к следующей метке case.)
Ниже приводится более реальный пример использования инструкции switch; он преобразует значение в строку способом, зависящим от типа значения:
function convert(x) { switch(typeof x) {
case 'number': // Преобразуем число в шестнадцатеричное целое return x.toString(16);
case 'string': // Возвращаем строку, заключенную в кавычки return '"' + x + '"';
case 'boolean': // Преобразуем в TRUE или FALSE, в верхнем регистре
6.6. Инструкция while
return x.toString().toUpperCase();
default:
// Любой другой тип преобразуем обычным способом
return x.toString()
}
}
Обратите внимание: в двух предыдущих примерах за ключевыми словами case следовали числа или строковые литералы. Именно так инструкция switch чаще всего используется на практике, но стандарт ECMAScript v3 допускает указание после case произвольного выражения.1 Например:
case 60*60*24:
case Math.PI:
case n+1:
case a[0]:
Инструкция switch сначала вычисляет выражение после ключевого слова switch, а затем выражения case в том порядке, в котором они указаны, пока не будет найдено совпадающее значение.2 Факт совпадения определяется в соответствии с оператором идентичности ===, а не оператором равенства ==, поэтому выраже_ ния должны совпадать без какого_либо преобразования типов.
Обратите внимание: использование выражений case, имеющих побочные эффек_ ты, такие как вызовы функций и присваивания, не является хорошей практи_ кой программирования, т. к. при каждом исполнении инструкции switch вычис_ ляются не все выражения case. Когда побочные эффекты возникают лишь в не_ которых случаях, трудно понять и предсказать поведение программы. Безопас_ нее всего ограничиваться в выражениях case константными выражениями.
Как объяснялось ранее, если ни одно из выражений case не соответствует выра_ жению switch, инструкция switch начинает выполнение с инструкции с меткой default:. Если метка default: отсутствует, инструкция switch полностью пропус_ кается. Обратите внимание, что в предыдущих примерах метка default: указана в конце тела инструкции switch после всех меток case. Это логичное и обычное место для нее, но на самом деле она может располагаться в любом месте внутри инструкции switch.