Перейти к содержанию

Книга JavaScript/Спецификация языка

Материал из Викиучебника — открытых книг для открытого мира

{{Готовность|0%}}

Под спецификацией языка программирования понимается стандартизация его синтаксиса и семантики. Как не зная алфавита и построения предложений, бессмысленно изучение естественного языка, так же бессмысленно дальнейшее изучение JavaScript без представленных в этой главе сведений.

Основы синтаксиса

[править]

JavaScript — язык с Си-подобным синтаксисом. Все элементы в нём, в том числе и ключевые слова, зависят от регистра, поэтому, например, названия переменных test и Test различны. Программа на JavaScript состоит из множества инструкций, которые выполняется пошагово. В связи с этим ошибка в какой-нибудь инструкции хоть и приводит к прерыванию работы всей программы, но все предыдущие корректные инструкции при этом будут выполнены. Эта особенность упрощает отладку программ, однако, с другой стороны, некоторые ошибки могут быть обнаружены лишь при выполнении инструкции, содержащей ошибку. Таким образом, в отличие от компилируемых языков, отладчик не может обнаружить ошибку, просто заранее проанализировав текст программы.

Инструкции в JavaScript завершаются точкой с запятой, но интерпретатор способен сам определить конец инструкции, поэтому они необязательны, хотя очень желательно всё же всегда ставить их — это поможет избежать ошибок и поспособствует читабельности программы. Кроме того, это позволит избежать снижения быстродействия, поскольку интерпретатор вынужден дополнительно анализировать инструкцию для определения её завершения в случае отсутствия точки с запятой.

Пример инструкции:

let sum = a + b;

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

sum = x + y;
sum=x+y ;
sum =x+ y;

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

x = 
2+1;
console.log("Java"+
"Script");
//JavaScript

Несмотря на то, что данный код без проблем выполнится, не сто́ит разделять инструкцию переносами, кроме некоторых случаев, когда без переноса инструкция получается слишком длинной. Например, в случае объявления длинных строк.

JavaScript позволяет объединять несколько инструкций в блок кода с помощью фигурных скобок { }:

{
  let sum = a + b;
  let result = sum - 2;
  console.log(result);
}

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

if(x > 0){
  let sum = x + 1;
  console.log(sum);
}

В конструкциях вроде if или for блоки обязательны только если инструкций несколько, если же она одна, фигурные скобки можно опустить. Однако на практике всё же рекомендуется их ставить даже для одной инструкции.

Наличие блоков кода проясняет намерения программиста и предотвращает ошибки при изменениях кода.

Блок кода, ограниченный фигурными скобками, также часто называют составным выражением. Всё, что помещено внутрь составного выражения, получает собственную область видимости. Если переменная объявлена с помощью let внутри составного выражения, то она существует только пока выполняется код составного выражения. За пределами фигурных скобок в этом случае переменная будет недоступной.

Константы и переменные

[править]

Переменные

[править]

Переменные в JavaScript назначаются тремя способами:

1. С помощью оператора «=»: ''переменная'' = ''значение''. Пример:

x = 1; // переменной x задаётся значение 1

При таком способе присваивания значения переменной она автоматически объявляется в глобальной области видимости (в браузере — как свойство объекта window).

2. С помощью ключевого слова var и оператора «=»: var ''переменная'' или var ''переменная'' = ''значение''. Пример:

var x;
x = 1;
// или
var x = 1;

Второй способ отличается от первого тем, что можно назначать сразу несколько переменных:

var x = 1, y = 2;

А также тем, что второй способ определяет значение переменной только в своём контексте, ограниченном функцией, в теле которой она объявлена:

function one(){ x = 1;} 
function two(){var y = 2;}
one();
two();
console.log(x);
//1
console.log(y);
//ReferenceError: x is not defined

Если присвоить значение переменной без её объявления, JavaScript неявно объявит эту переменную за вас. Однако переменные, объявленные таким образом, всегда создаются как глобальные, даже если они работают только в теле функции. Способ присвоения значения переменной без её явного объявления не рекомендуется, поскольку создаёт трудности при отладке приложения.

3. С помощью ключевого слова let: let ''переменная'' или let ''переменная'' = ''значение''. Пример:

let x;
x = 1;
// или 
let x = 1;

Отличие let от var состоит в том, что с помощью var возможно так называемое поднятие, при котором объявление переменной может следовать после присвоения ей значения (только в том же блоке кода). Например:

{
  x = 3;
  var x;
  console.log(x);
}
//3

В случае использования let возникнет ошибка:

{
  x = 3;
  let x;
  console.log(x);
}
//ReferenceError

Переменная, объявленная с помощью let, в отличие от var действует лишь в пределах своего блока кода, то есть её область видимости ограничена ближайшей конструкцией, внутри которой она объявлена. Это позволяет избежать очень неприятного поведения, например, в циклах:

for(var i = 0; i < 10; ++i){}
console.log(i);
//10

for(let i = 0; i < 10; ++i){}
console.log(i);
//ReferenceError

В данном примере в случае с var видимость переменной вышла за пределы цикла, потому что её область видимости ограничена лишь функцией.

В именах переменных могут использоваться латинские буквы (a…z, A…Z), цифры (0…9), знак доллара ($) и знак подчёркивания (_), при этом нельзя использовать цифру первой. Необходимо помнить, что JavaScript — регистрозависимый язык, и переменные X и x будут считаться различными.

Учтите, что неявное объявление глобальных переменных (без использования ключевых слов var или let) приводит к тому, что эти переменные назначаются как свойства объекту window, из-за чего занимают объём в оперативной памяти, выделенной браузеру, вплоть до закрытия окна, даже если они никогда не будут использоваться в ходе выполнения программы. Объявление let помогает избежать многих проблем в больших программах, где трудно отслеживать поведение кода. В связи с этим настоятельно рекомендуется использовать объявление let во всех случаях. Профессиональный уровень программирования предполагает, что программист способен вообще обойтись без глобальных переменных.

Константы

[править]

Константы (постоянные) объявляются в JavaScript с помощью ключевого слова const. В отличие от объявления переменных с помощью var и let, константам должно присваиваться значение в объявлении. Например:

{
  const c = 299792458;
  console.log(c);
}
//299792458

Попытка объявления без присваивания приводит к ошибке:

{
  const c;
}
//SyntaxError

Константы, в отличие от переменных, нигде во всей программе не могут изменить своё значение:

{
  const c = 299792458;
  c = 1;
}
//Error: assignment to constant variable

Однако каждая константа действительна лишь в своей области видимости:

{
  const x = 1;
  console.log(x);
}
{
  const x = 2;
  console.log(x);
}
//1
//2
console.log(x);
//Error: x is not defined

Типы данных

[править]

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

Пример:

{
  let a,b;
  a = 3;
  b = a;
  a = 4;
  console.log(b);
}
//3

В данном случае переменная b вначале получает значение от переменной a, но в дальнейшем сохраняет значение неизменным, несмотря на изменение переменной a.

Совсем по-другому ведёт себя ссылочный тип. В отличие от примитивного, он не хранит значение, а лишь ссылку на него. Таким образом, изменение значения в одной переменной повлечёт за собой изменение во всех других, ссылающихся на неё.

Пример:

{
  let a = new Array();
  let b;
  a[1] = 3;
  b = a;
  console.log(b[1]);
  a[1] = 4;
  console.log(b[1]);
}
//3
//4

b[1] изменила значение вслед за изменением a[1], поскольку a и b хранят в себе не данные массива, а только ссылку на него.

Стандарт ES6 предполагает 6 примитивных типов, 2 из которых специальные, а также множество ссылочных, которые ведут себя очень похожим образом и по сути являются экземплярами одного конкретного ссылочного типа (reference type). Поэтому все их мы описывать не будем. Ссылочные типы часто называют классами, что является ошибкой.

JavaScript является слаботипизированным языком, что имеет свои достоинства и недостатки. Для определения типа переменной существует оператор typeof, который возвращает тип данных в виде строки:

alert(typeof "23");
//string
alert(typeof 23);
//number
let x = true;
alert(typeof x);
//boolean
x = 10;
alert(typeof x);
//number


Специальные типы данных

[править]
  • null — пустой объект,
  • undefined — неопределённая переменная.


undefined

[править]

Объявленная, но не инициализированная переменная (которой не присвоено значение) будет иметь тип undefined, который может принять единственный аргумент undefined:

let x;
alert(typeof x);
//undefined
console.log(x);
//undefined

Не сто́ит никогда назначать значение undefined переменным, хотя это и не приведёт к ошибке. Это значение необходимо лишь для чтения.

Обращение к неинициализированной переменной допустимо, но недопустимо обращение к необъявленной переменной, хотя её тип (но не значение!) тоже будет undefined.

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

var a;
if(!a){
   //этот блок выполнится
}
if(a){
   //этот блок не выполнится
}
if(b){
   /*этот блок вернёт ошибку, так как переменная "b" не объявлена*/
}

На этом использование undefined заканчивается.


Тип null тоже содержит единственный аргумент — значение null, тем не менее при использовании оператора typeof будет возвращена строка "object". Это происходит потому, что фактически null является указателем на пустой объект:

let x = null;
console.log(typeof x);
//object

В отличие от undefined переменной можно прямо присваивать значение null. Это часто используется для очищения оперативной памяти, поскольку сборщик мусора в JavaScript считает переменную со значением null несуществующей. Кроме того, созданную переменную, которая позже может получить в качестве значения объект, желательно инициализировать значением null. Это позволяет отличать ошибочный пропуск инициализации от намеренного.

Тип null, как и undefined, является ложным, что можно использовать в условных конструкциях:

var a = null;
if(!a){
   //этот блок выполнится
}
if(a){
   //этот блок не выполнится
}

Примитивные типы данных

[править]
  • логический (boolean) — определяется отсутствием кавычек и используется для значений true (1) или false (0),
  • числовой (number) — определяется отсутствием кавычек и используется для чисел (не символов),
  • строковый (string) — определяется двойными или одинарными кавычками и используется для хранения символьных последовательностей,
  • символ (symbol) — одиночный символ с идентификатором.


Логический тип, может принимать одно из двух значений: true или false. Хотя в двоичной интерпретации они подразумевают значения 1 и 0, при строгой проверке оказываются не равны им:

if(true === 1){
    console.log("Равны");
}
else{
    console.log("Не равны");
}
//Не равны

Но при нестрогой, при использовании оператора "==", равны. Это связано с тем, что при нестрогом сравнении происходит приведение типов.

Присвоить значение типа Boolean переменной можно следующим образом:

let enabled = true;
let disabled = false;

Значения этого типа легко переключаются с помощью оператора логического отрицания:

let enabled = true;
console.log(!enabled);
//false

У всех значений других типов есть свои логические эквиваленты:

Тип данных Преобразуется в true Преобразуется в false
boolean true false
string "любая непустая строка" "" (пустая строка)
number Любое ненулевое число (включая бесконечность) 0, NaN
object Любой объект null
undefined undefined

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


Тип Number служит для представления чисел, включая как целые числа, так и дробные с плавающей точкой в формате IEEE-754. Тип Number способен представить числа в десятичной, восьмеричной и шестнадцатеричной системах счисления. Десятичная система используется "как есть":

let x = 123;
console.log(typeof x);
//number

В восьмеричной записи требуется добавлять ноль(0) впереди, а затем цифры в восьмеричном формате (от 0 до 7). В шестнадцатеричной записи — перед числом должен стоять литерал 0x (не зависит от регистра), а затем цифры в шестнадцатеричном формате (от 0 до 9 и от A до F).

let octNum = 071; 
//восьмеричное число, равное 57
console.log(octNum);
//57
let hexNum = 0x1f; 
//шестнадцатеричное число, равное 31
console.log(hexNum);
//31

В строгом режиме восьмеричный формат не поддерживается и приведёт к ошибке. Если в литерале обнаружится цифра не из диапазона цифр восьмеричной системы счисления, будет совершена попытка интерпретации этого числа в десятичной системе (начальный нуль будет проигнорирован).

Числа, созданные как восьмеричные и шестнадцатеричные, автоматически переводятся интерпретатором в десятичную форму, поэтому все арифметические операции с ними производятся как с десятичными.

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

Пример:

let x = 0.3;
let y = 12.1;
let z = .1; //допустимо, означает 0.1

Очень большие или очень маленькие числа автоматически представляются в экспоненциальной форме (e-notation), если они содержат более 21 знака в случае целого числа или минимум 6 нулей после точки в случае дробного числа с плавающей точкой. Пример экспоненциальной записи:

let num = 0.0000003;
console.log(num);
//3e-7

Экспоненциальную запись можно прямо назначать переменной:

let num = 5e+8;
console.log(num);
//500000000

Как видно, данная запись означает число, умноженное на 10 в соответствующей степени.

Число с плавающей точкой в любом случае не может превысить 18 знаков после точки. Поэтому такие числа можно назначать только в экспоненциальной записи. Записанное обычным способом такое число в экспоненциальную форму автоматически не преобразуется, а просто обрежется по 18 знак после точки.

Диапазон значений, который охватывает тип Number, отличается в разных браузерах и средах исполнения. Чтобы узнать крайние значения, можно получить их с помощью свойств суперглобального объекта Number:

console.log(Number.MAX_VALUE);
console.log(Number.MIN_VALUE);
console.log(Number.MAX_SAFE_INTEGER);
console.log(Number.MIN_SAFE_INTEGER);

/*В моём браузере результаты таковы:
1.7976931348623157e+308
5e-324
9007199254740991
-9007199254740991
*/

Результаты вычислений, выходящие за пределы этих значений, преобразуются в специальные значения Infinity и -Infinity соответственно.

Например, значение Infinity можно получить в результате деления любого числа на 0:

let y = 3/0;
console.log(y);
//Infinity

Значения с плавающей точкой имеют точность до 16 знаков после точки, дальше в результате арифметических действий цифры могут случайно отклоняться. При этом числа с плавающей точкой не округляются автоматически (например, при сложении 0.1 и 0.2 получается не 0.3, а 0.30000000000000004), в результате чего сильно влияют на точность и длительность дальнейших вычислений. По этой причине следует отказываться от чисел с плавающей точкой в пользу целых чисел везде, где это только возможно. И уж ни в коем случае нельзя проверять конкретные значения с плавающей точкой в условных конструкциях:

let x = 0.6;
if(x/3 == 0.2){
  //вопреки ожиданиям, этот блок не выполнится
  //не делайте так!
}

Кроме того, учтите, что в связи с ограниченной точностью некоторые известные алгебраические функции не дадут того результата, который математически должен получиться, например, тангенс 90° не даст Infinity:

let alpha = Math.PI/2;
console.log(Math.tan(alpha));
//16331239353195370

Зато округление может внезапно возникнуть в некоторых случаях, например:

console.log(0.6666666666666666*3);
//2
console.log(0.6666666666666667*3);
//2

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

NaN — это специальное значение типа Number, которое предназначено для результата операции, которая должна была возвратить числовое значение, но не сделала этого, но и не сгенерировала ошибку. "NaN" означает "не число" (Not a Number). Значение NaN позволяет продолжить работу программы в тех случаях, которые во многих других языках привели бы к критической ошибке, например в случае извлечения квадратного корня из отрицательного числа:

let x = Math.sqrt(-2);
console.log(x);
//NaN

Значение NaN обладает некоторыми особенными свойствами. Во-первых, любая операция с NaN даёт в результате тоже NaN. Во-вторых, NaN не равен никакому другому числу и вообще никакому значению, в том числе и самому себе. Поэтому, чтобы отследить, не получила ли переменная значение NaN, необходимо использовать специальную функцию isNaN(), которая принимает один аргумент любого типа и пытается преобразовать его в число. Если это не получается, то возвращается true, если получается, то false:

console.log(isNaN(NaN)); //true
console.log(isNaN(12)); //false
console.log(isNaN("hello")); //true
console.log(isNaN(true)); //false

Не пытайтесь ничего сравнивать со значением NaN!

Преобразования в числа
[править]

Существует три функции преобразования нечисловых значений в числа:

  • Number();
  • parseInt();
  • parseFloat();

Функция Number() работает с любым значением, а две других — только со строками.

Для функции Number() существуют следующие правила:

  • Логические значения true и false превращаются в 1 и 0 соответственно.
  • Числа возвращаются без изменений.
  • Значение null превращается в 0.
  • Значение undefined превращается в NaN.
  • Строки преобразуются по особым правилам:
    • если строка содержит только числовые символы с начальным знаком "+" или "-", либо без знака, то она преобразуется в соответствующее десятичное число, при чём начальные нули игнорируются;
    • если строка содержит число с плавающей точкой в правильном формате (с точкой), она преобразуется в это число, лишние нули тоже игнорируются;
    • шестнадцатеричное число в правильном формате преобразуется в соответствующее ему десятичное число;
    • пустая строка возвращает 0;
    • всё остальное возвращает NaN;

Внимание: функция Number() в точности соответствует унарному оператору +. Поэтому, например, запись +"123" эквивалентна записи Number("123"), если перед ней не стоит другая строка или литерал:

let x = "123";
let y = +x;
console.log(y + 1);
//124

Примитивный тип String служит для представления строк. Строка — это последовательность (если быть точнее, массив) 16-разрядных знаков в формате Юникод. Для представления строки необходимо заключить текст в одинарные ('), двойные (") или обратные (`) кавычки:

let lastname = "Иванов";
let firstname = 'Иван';
let fathername = `Иванович`;

Все три синтаксических варианта одинаковы, однако открывающие и закрывающие кавычки не должны отличаться:

let name = "Вася';
//Error: Invalid or unexpected token

Чтобы использовать кавычки как часть строки, нужно для обозначения строки использовать другие кавычки. Это может выглядеть, будто одну строку поместили внутрь другой, что может быть очень полезно для парсинга строк с помощью функции eval():

let instruction = 'let str = "строка";';

Не забывайте, что строка по сути является массивом символов. Это легко проверить:

let name = "Федя";
console.log(name[2]);
console.log(name.length);
//д
//4

Как видите, для строк справедливы некоторые операции, применяемые в отношении массивов. В некоторых случаях это может быть очень удобно.

Строки могут быть объединены с помощью оператора "+", при чём не имеет значения, с помощью одинаковых или разных кавычек эти строки обозначены:

let language = "Java"+'Script';
console.log(language);
//JavaScript

Ссылочные типы данных

[править]
  • массив (array),
  • объект (object) — программный объект (ссылка на него),
  • функция (function) — определение функции.

Операторы

[править]

Комментарии

[править]

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

1. Оператор «//» используют, чтобы текст, расположенный справа от оператора до конца строки, сделать комментарием: ''программа'' // ''комментарий''. Пример:

x = 3; // Присвоение переменной x значения 3
y = 5; // Присвоение переменной y значения 5

2. Операторы «/*» и «*/» используют, чтобы текст расположенный внутри операторов сделать комментарием: ''программа'' /* ''комментарий'' */ ''программа''. Пример:

x = 3;   /* Присвоение переменной x значения 3,
           а переменной y — 5: */
y = 5;

Арифметические

[править]

Арифметические операции производятся только с данными одного типа. JavaScript способен сам определять тип данных, однако не стоит уповать на него — рекомендуется самостоятельно следить за их типом.


Оператор Название Пример Результат
+ Сложение x + y Сложение двух чисел или склеивание двух строк
- Вычитание x - y Вычитание y из x или удаление строки y из строки х
* Умножение x * y Перемножение двух чисел
/ Деление x / y Деление числа x на число y
% Деление по модулю (остаток) x % y Остаток от деления числа x на число y
++ Инкремент (увеличение на 1) x++ Эквивалентно x+1
-- Декремент (уменьшение на 1) x-- Эквивалентно x-1

Примеры использования:

6 + 3;    // результат 9
6 - 3;    // результат 3
6 * 3;    // результат 18
6 / 3;    // результат 2
5 % 3;    // результат 2
6++;      // результат 7
6--;      // результат 5

Можно использовать и с переменными:

x = 3;           // значение x — 3
y = 5;           // значение y — 5
z = x + y;       // значение z — 8

Возможно использование в выражениях со скобками:

4 + 5 * 2;       // результат 14
(4 + 5) * 2;     // результат 18

В арифметических операциях логические значения считаются: true — 1, false — 0:

5 + true;     // результат 6
5 + false;    // результат 5
4 * true;     // результат 4
4 * false;    // результат 0
true + true;  // результат 2
true + false; // результат 1

Оператор сложения можно использовать для склейки строк:

"Java" + "Script";  // результат "JavaScript"
a = "Java"; 
b = "Script"; 
a + b; // результат "JavaScript"
"Уровень" + 5; // результат "Уровень5"
"Уровень" + true; // результат "Уровеньtrue"
"1" + "2"; // результат "12"

Другие арифметические операторы со строками дают значение NaN:

"J" * 5; // результат NaN
"J" - 5; // результат NaN
"J" - "J"; // результат NaN

Если вы не знаете, то NaN — это значение переменной, когда совершается неккоректное действие, например a = 1 * "Hello! ". NaN не равен ни одному числу, даже самому себе.

Основные конструкции

[править]

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

Функции

[править]

JavaScript как и многие другие языки программирования построен на функциях. Синтаксис:

function <имя_функции> (<параметры>) {
    <операторы>;
    return <возвращаемое_значение>; 
}

Оператор return возвращает значение, в следующем примере это будет показано. Параметры (или аргументы) это такие переменные, значение которых мы задаём при вызове функции:

function plus(a,b) {
    return (a + b); // Мы возвращаем сумму параметров a и b. 
}
var c = plus(1,2); // Переменная c получит значение 3.

Условия

[править]

Условия позволяют выполнить один или несколько операторов только при выполнении определённого условия. Синтаксис:

if(<условие>) {
    <операторы>;
}
else { // Иначе, т. е. если условие не выполнилось.
    <операторы>;
}

Циклы

[править]

while (цикл с предусловием)

[править]

Цикл будет продолжаться до того момента, когда условия перестанут выполняться. Синтаксис:

while(<условие>) {
    <операторы>;
}

do…while (цикл с постусловием).

[править]

Цикл do…while отличается от while только тем, что условие проверяется в конце выполнения блока, соответственно он выполнится минимум 1 раз. Синтаксис:

do {
   <операторы>;
}
while(<условие>)

for (итерационный цикл, счётчик)

[править]

Синтаксис:

for(var <переменная> = <начальное_значение>; <условие>; <шаг_цикла>) {
   <операторы>;
}

В циклах for создаётся отдельная переменная, задаётся условие с этой переменной, при котором будет продолжаться выполнение цикла. И при каждом выполнении производится какая-либо операция. Например:

for(var i = 0; i < 10; i++) {
   <операторы>; // повторяется 10 раз
}

Подробное разъяснение: создаётся переменная i и цикл выполняется пока i меньше или равно 10, и при каждой итерации (т.е. одном выполнении цикла) к переменной i прибавляется 1 (инкремент), соответственно цикл выполнится 10 раз.

Переключатели

[править]

Переключатели позволяют сравнить одну переменную с большим количеством констант, хотя их можно заменить простыми условиями. Но переключатели более лаконичны. Синтаксис:

var a; 
switch(a) {
case 1: // Если a = 1
    <операторы>;
    break;
case 2: // Если a = 2
    <операторы>;
    break;
default: // остальные значения
    <операторы>;
    break;
}

case сравнивает переменную, указанную в switch(переменная). break прерывает выполнение case или default, т. е. если он будет отсутствовать при выполнении хотя бы первого case, выполнятся все последующие и defalult. default выполнится только если ни один из операторов case.