Выражения и операторы в JavaScript
Перед чтением: Операторы — общие понятия оператора, операнда, приоритетов и типов операций без привязки к языку.
Выражения и операторы
JavaScript — язык, в котором практически всё есть выражение. Это фундаментальное свойство, определяющее синтаксис и семантику языка: от простейших вычислений до сложных императивных конструкций. Чтобы говорить о поведении кода осознанно, необходимо чётко разделять выражения (expressions) и операторы (operators), понимать их взаимосвязь, приоритеты, ассоциативность и контекст вычисления. Эта глава посвящена систематическому описанию этих понятий — от первичных элементов до сложных композиций, используемых в реальных программах.
Что такое выражение?
Выражение — это любой фрагмент кода, который вычисляется и возвращает значение. В отличие от инструкций (statements), которые описывают действия, выражения существуют ради своего результата. Многие инструкции в JavaScript могут содержать выражения, но не каждое выражение является инструкцией в строгом смысле — хотя благодаря особенностям синтаксиса JavaScript (например, отсутствию строгого разделения expression и statement в контексте блока) эта грань часто размыта.
Примеры выражений:
42— литерал, выражение, возвращающее число."привет"— строковый литерал.x + y— бинарное выражение, возвращающее сумму.f()— вызов функции, выражение, возвращающее результат её выполнения.{ a: 1 }— литерал объекта.true ? 'да' : 'нет'— условное выражение.a = b = 5— цепочка присваиваний, возвращающая значение5.
Любое выражение имеет тип и значение (которое может быть undefined, null, 0, NaN, объектом и так далее), и может быть использовано в любом контексте, где ожидается значение — в правой части присваивания, в качестве аргумента функции, в условии if, в возвращаемом значении и так далее.
Важно: в JavaScript даже блок кода в фигурных скобках { ... } может быть выражением (например, в стрелочной функции с телом-блоком), но только если он находится в подходящем контексте — например, внутри do-выражения (предложение на стадии Stage 3 на момент 2025 года) или как часть switch-выражения в будущих версиях. На текущий момент (ECMAScript 2025) блок сам по себе — инструкция, но не выражение; однако многие синтаксические конструкции, внешне похожие на инструкции, на самом деле являются выражениями.
Что такое оператор?
Оператор — это символ или ключевое слово, которое применяется к одному или нескольким операндам (выражениям) и образует новое выражение. Операторы определяют операции — арифметические, логические, побитовые, сравнения, присваивания и другие.
Классификация операторов по количеству операндов:
- Унарные — требуют один операнд (например,
typeof x,+y,!flag); - Бинарные — требуют два операнда (например,
a + b,x === y,p && q); - Тернарные — единственный в языке: условный оператор
? :, требует три операнда.
Операторы обладают приоритетом (precedence) и ассоциативностью (associativity), определяющими порядок вычисления в составных выражениях. Например, в a + b * c сначала вычисляется b * c, потому что * имеет более высокий приоритет, чем +. Если приоритеты равны (например, a - b - c), ассоциативность (в данном случае левая) определяет, что вычисление идёт слева направо: (a - b) - c.
Рассмотрим категории операторов и выражений в JavaScript последовательно, от простейших к более сложным.
Play ITЗагрузка интерактивного демо…
Первичные выражения
Первичные выражения — это атомарные единицы, из которых строятся более сложные конструкции. Они не содержат в себе других операторов и служат отправной точкой для разбора любого выражения.
1. Литералы
Литералы — это непосредственные значения, записанные в коде. Каждый тип данных имеет свой синтаксис литералов:
- Числовые:
42,3.14,0xFF,0b1010,1e6; - Строковые —
'одинарные',"двойные",`шаблонные ${expr}`(шаблонные строки будут рассмотрены отдельно); - Логические:
true,false; nullиundefined;- Регулярные выражения:
/abc/gi; - BigInt:
123n.
Литералы всегда вычисляются в значения соответствующих типов. Стоит подчеркнуть, что строковые литералы в одинарных и двойных кавычках семантически эквивалентны — различие чисто синтаксическое (удобство экранирования). Шаблонные строки, в отличие от них, являются вызовом конструктора, и их вычисление включает интерполяцию и, при наличии тега, вызов функции-тега.
2. Идентификаторы
Имя переменной, параметра или свойства, определённое в текущей области видимости, — это выражение, возвращающее значение, связанное с этим именем. Например, x, count, isReady. Разрешение имени происходит по цепочке областей видимости (scope chain), и если имя не найдено, возникает ReferenceError (если только не используется в контексте typeof, который допускает неопределённые идентификаторы).
function testScope() {
let x = 10;
// 'x' — это выражение, возвращающее значение 10
console.log(x);
let count = 5;
let isReady = true;
// Вывод: 10, 5, true
console.log(x + count, isReady);
}
testScope();
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Если имя не найдено в текущей области, поиск продолжается во внешней области (замыкание).
Код ITЗагрузка примера кода…
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Если имя не найдено ни в одной из областей видимости, возникает ошибка ReferenceError, если обращение происходит вне контекста typeof.
Код ITЗагрузка примера кода…
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Параметры функции тоже являются выражениями, доступными в теле функции.
Код ITЗагрузка примера кода…
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Доступ к свойству объекта (obj.prop) также является выражением, возвращающим значение свойства. Если свойство отсутствует, возвращается undefined (не вызывает ReferenceError).
Код ITЗагрузка примера кода…
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
3. Ключевое слово this
this — особое выражение, значение которого определяется контекстом вызова, а не местом определения. В глобальном контексте (вне функций и в не-strict mode) this ссылается на глобальный объект (window в браузере, global в Node.js); в strict mode — undefined. В методах объекта this указывает на объект, через который вызван метод. В стрелочных функциях this наследуется от лексического окружения. Конструкторы и bind/call/apply также влияют на this.
Значение this зависит от режима выполнения кода.
Код ITЗагрузка примера кода…
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
В методах обычного объекта this ссылается на объект, через точку которого вызван метод.
Код ITЗагрузка примера кода…
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
При использовании оператора new для вызова функции, this внутри функции автоматически привязывается к новому создаваемому объекту.
Код ITЗагрузка примера кода…
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на работе с созданием объектов.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Стрелочные функции не имеют собственного this. Они захватывают значение this из лексического окружения, в котором были объявлены.
Код ITЗагрузка примера кода…
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Методы функций позволяют явно задать значение this.
Код ITЗагрузка примера кода…
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
В классах ES6 поведение this аналогично обычным функциям-конструкторам, но синтаксис отличается. Важно помнить, что методы класса должны быть определены корректно, чтобы избежать потери контекста.
Код ITЗагрузка примера кода…
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на работе с созданием объектов.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
4. Литералы массивов и объектов
[1, 2, 3]— массив, выражение, создающее новый объектArray;{ x: 1, y: 2 }— объект, создаётся экземплярObjectс указанными свойствами.
Эти конструкции — выражения, а не инструкции. Их можно использовать в любом месте, где ожидается значение — присвоить переменной, передать в функцию, вернуть из неё. Синтаксис допускает вычисляемые ключи ({ [key]: value }), сокращённые методы, геттеры/сеттеры — всё это входит в единый механизм инициализации объектов.
5. Литералы функций
Функции в JavaScript — объекты первого класса. Их можно определять прямо в выражениях:
- Анонимное функциональное выражение:
function (x) { return x * 2; }; - Именованное функциональное выражение:
function double(x) { return x * 2; }(имяdoubleдоступно только внутри функции); - Стрелочная функция:
x => x * 2или(x, y) => ({ sum: x + y }).
Функциональное выражение создаёт объект функции и возвращает ссылку на него. Оно может быть использовано в любом контексте, где нужен объект — присвоено переменной, передано как аргумент, возвращено из другой функции.
6. Литералы классов
Классы в ES6 — это синтаксический сахар над функциями-конструкторами, но с ключевыми отличиями в семантике (например, строгий режим по умолчанию, отсутствие подъёма). Класс-выражение:
const MyClass = class {
constructor(name) {
this.name = name;
}
greet() {
return `Привет, ${this.name}`;
}
};
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на работе с созданием объектов.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Такой литерал — выражение, возвращающее конструктор класса. Он может быть анонимным (class { ... }) или именованным (class MyClass { ... }), причём имя в последнем случае также доступно только внутри тела класса.
7. Шаблонные строки
Шаблонные строки — это выражения, заключённые в обратные кавычки: `Привет, ${name}!`. При вычислении интерполируются значения, возвращаемые вложенными выражениями (${...}), и конкатенируются в итоговую строку.
Если перед шаблонной строкой стоит идентификатор (например, tag), это становится тегированной шаблонной строкой — особой формой вызова функции:
function tag(strings, ...values) {
return strings[0] + values[0].toUpperCase() + strings[1];
}
const name = "мир";
const result = tag`Привет, ${name}!`; // → "Привет, МИР!"
Разбор:
- Функция
tagвыступает тегом для шаблонной строки и получает разобранные части шаблона. - Параметр
stringsсодержит статические куски строки, а...values— интерполированные значения. values[0].toUpperCase()преобразует подставленное значение к верхнему регистру.- Конструкция
tag\...`` вызывает функцию не как обычный вызов, а через механизм tagged templates. const resultполучает уже собранную строку с модифицированной вставкой.- Такой подход применяют для экранирования, локализации и построения DSL без ручного парсинга.
- Ключевые элементы: rest-параметр
..., шаблонные строки и метод строкиtoUpperCase.
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
В этом случае tag получает массив "голых" строковых частей и список значений выражений. Это мощный инструмент для создания DSL, безопасного экранирования, локализации и других метапрограммных задач.
Левосторонние выражения (Left-Hand Side Expressions)
Эта категория объединяет выражения, которые могут стоять слева от оператора присваивания или использоваться для вызова (то есть обозначают место в памяти или свойство, доступное для записи или вызова).
1. Доступ к свойствам
- Точечная нотация:
obj.prop— компилятором трактуется какobj["prop"], но ключ должен быть валидным идентификатором; - Квадратные скобки —
obj[key]— позволяет использовать динамические или некорректные с точки зрения идентификаторов ключи (obj["123"],obj["class"],obj[someVar]).
Оба способа возвращают ссылку на свойство — "место", откуда значение берётся и куда может быть записано. Это критически важно для понимания присваивания и мутаций.
2. Вызовы
Вызов функции f(), метода obj.method(), конструктора new C() — технически это операции над левосторонними выражениями. Выражения f, obj.method, C сначала вычисляются как ссылки, затем к ним применяется операция вызова.
3. Оператор new
new Date()
new MyClass(arg)
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на работе с созданием объектов.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Оператор new создаёт новый объект, устанавливает его [[Prototype]] на C.prototype, вызывает функцию C с this, указывающим на новый объект, и возвращает либо результат вызова (если это объект), либо сам объект. Это выражение возвращает ссылку на созданный экземпляр.
4. super
Ключевое слово super используется в методах классов для доступа к свойствам и вызова методов родительского класса. super.method() эквивалентно вызову Object.getPrototypeOf(this).method.call(this), но с корректной привязкой this и проверками контекста (можно использовать только внутри методов класса, не в стрелочных функциях и не в обычных функциях).
5. import.meta
Метаданные текущего модуля: import.meta.url содержит абсолютный URL модуля, import.meta.resolve() (в некоторых средах) позволяет разрешать относительные пути. Это выражение доступно только в модульном контексте и возвращает объект метаданных.
Унарные операторы
Унарные операторы применяются к одному операнду и формируют выражение, возвращающее новое значение (или, в случае некоторых, побочный эффект). Порядок применения: оператор стоит слева от операнда (префиксная форма), за исключением постфиксных ++ и --.
1. typeof
Оператор typeof возвращает строку, указывающую тип операнда на этапе выполнения. Он безопасен: не вызывает ошибок даже при обращении к необъявленным переменным (в отличие от большинства других операций).
Результаты typeof:
| Операнд | Результат | Комментарий |
|---|---|---|
undefined | "undefined" | |
null | "object" | Историческая ошибка, сохранённая для обратной совместимости. Это не объект, но результат фиксирован. |
true, false | "boolean" | |
Числа (42, 3.14, NaN) | "number" | NaN — тоже число по типу. |
123n | "bigint" | |
| Строки | "string" | |
Символы (Symbol()) | "symbol" | |
| Функции | "function" | Не отдельный тип, а подмножество объектов, но typeof делает исключение. |
| Любой другой объект | "object" | Включая массивы, даты, регулярки, обычные объекты. |
Примеры:
typeof undeclaredVariable; // "undefined" — безопасно!
typeof null; // "object"
typeof []; // "object"
typeof /regex/; // "object" (в большинстве реализаций)
typeof (() => {}); // "function"
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
typeof работает на уровне runtime type. Он не различает массивы и обычные объекты — для этого нужны другие средства (Array.isArray()).
2. void
Оператор void вычисляет свой операнд, отбрасывает результат и возвращает undefined. Чаще всего используется в двух контекстах:
- Гарантированное получение
undefined, независимо от возможного переопределения глобальногоundefined(актуально в старых средах, гдеundefinedбыл изменяемым):
const trulyUndefined = void 0;
- В
javascript:-ссылках, чтобы предотвратить переход или возврат значения:
<a href="javascript:void(0)">Нажми</a>
Любое выражение после void будет выполнено (включая побочные эффекты), но результат всегда undefined.
3. delete
Оператор delete пытается удалить свойство объекта. Его поведение часто неправильно интерпретируется.
- возвращает
true, если свойство успешно удалено или не существовало;false, если свойство неконфигурируемо (например, наследуется отObject.prototype, или объявлено какconfigurable: false).
delete obj.prop
Разбор:
-
Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
-
Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
-
Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
-
Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
-
В примере акцент сделан на пошаговом выполнении кода.
-
Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
-
Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
-
Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
-
не удаляет переменную, возвращает
trueв нестрогом режиме,SyntaxErrorв strict mode.
delete variable
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
— делает ячейку "дыркой" (hole), длина массива не меняется, и arr[index] станет undefined (но index in arr — false).
delete arr[index]
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Пример:
const obj = { a: 1, b: 2 };
Object.defineProperty(obj, 'c', { value: 3, configurable: false });
delete obj.a; // true, 'a' удалён
'a' in obj; // false
delete obj.c; // false, 'c' не удалён
'c' in obj; // true
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
delete не освобождает память напрямую — он лишь удаляет привязку свойства к объекту. Сборщик мусора решает, освобождать ли память.
4. Унарные + и -
- Унарный
+преобразует операнд в число по алгоритмуToNumber. Эффективная заменаNumber(x).
+ "42" // 42
+ true // 1
+ false // 0
+ null // 0
+ undefined // NaN
+ [] // 0
+ [1] // 1
+ [1,2] // NaN
- Унарный
-делает то же самое, но дополнительно меняет знак. ДляNaNиInfinityзнак меняется соответствующе (-Infinity,-0).
Особое внимание — -0. Это отдельное значение типа number, эквивалентное 0 в сравнениях (-0 === 0 → true), но различимое через Object.is(-0, 0) → false или 1 / -0 → -Infinity.
5. Логическое отрицание !
Оператор ! преобразует операнд к логическому значению (по ToBoolean) и инвертирует его. Двукратное применение (!!x) — идиома для явного приведения к boolean.
Ложные значения (falsy) в JavaScript:
false, 0, -0, 0n, "", null, undefined, NaN.
Все остальные — истинные (truthy).
!"" // true
!"hello" // false
!!{} // true
!![] // true
!!null // false
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
6. Побитовое НЕ ~
Применяет поразрядное дополнение: инвертирует все биты 32-битного целого представления операнда.
Поскольку ~x эквивалентно -(x + 1), часто используется в идиомах вроде:
if (~str.indexOf('подстрока')) { ... }
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на работе с условной логикой.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
— потому что indexOf возвращает -1, если не найдено, а ~(-1) === 0 (ложь), иначе — ненулевое число (истина). Однако в современном коде это считается плохой практикой; предпочтительнее str.includes('...').
7. Инкремент и декремент — ++, --
Существуют в двух формах:
- Постфиксная —
x++,x--— возвращает старое значение, затем изменяет переменную. - Префиксная —
++x,--x— сначала изменяет переменную, затем возвращает новое значение.
Применяются только к ссылкам (переменным, свойствам, элементам массива), не к выражениям (++(x + y) — ошибка).
let a = 5;
let b = a++; // b = 5, a = 6
let c = ++a; // c = 7, a = 7
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Важно: операторы создают побочный эффект — изменяют состояние. Их избыточное использование в сложных выражениях (arr[i++] = ++i) ведёт к нечитаемому и неопределённому поведению и строго не рекомендуется.
8. await
Оператор await может использоваться только внутри async-функции. Он приостанавливает выполнение функции до тех пор, пока промис (или thenable) не завершится, и возвращает:
- значение — если промис выполнился успешно;
- бросает исключение — если промис отклонён.
Если операнд не промис — await заворачивает его в Promise.resolve() и немедленно возвращает значение.
async function f() {
const val = await 42; // 42
const res = await fetch('/'); // ждёт ответа
return res.json();
}
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на работе с асинхронным выполнением.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
await делает асинхронный код похожим на синхронный, но не блокирует поток — выполнение других задач (например, обработчиков событий) продолжается.
Арифметические операторы
Арифметические операторы выполняют математические операции над числовыми значениями. Все (кроме +) преобразуют операнды к числу через ToNumber. Оператор + имеет двойное назначение: сложение чисел и конкатенация строк — и его поведение зависит от типов операндов.
1. Сложение +
Алгоритм:
- Вычисляются оба операнда.
- Каждый преобразуется к примитиву (
ToPrimitive, предпочтительно строка, если один из операндов — строка). - Если хотя бы один операнд — строка, происходит конкатенация.
- Иначе — числовое сложение.
Примеры:
1 + 2 // 3
"1" + 2 // "12"
1 + "2" // "12"
"hello" + [] // "hello" (массив → "" → конкатенация)
[] + [] // "" (оба → "", складываются)
{} + [] // "[object Object]" — осторожно: {} интерпретируется как блок в начале выражения!
({} + []) // "[object Object]" — теперь {} — объект.
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Особые случаи:
+0 + -0→+0Infinity + (-Infinity)→NaNNaN + что угодно→NaN
2. Вычитание -, умножение *, деление /, остаток %, возведение в степень **
Все эти операторы работают строго в числовом контексте: оба операнда приводятся к number (или bigint, но нельзя смешивать типы).
-:5 - 2→3;5 - "2"→3;"5" - "2"→3*:3 * 4→12;"3" * null→0/:7 / 2→3.5;1 / 0→Infinity;-1 / 0→-Infinity%: остаток от деления, не математический модуль. Знак результата совпадает со знаком делимого:
7 % 3 // 1
-7 % 3 // -1
7 % -3 // 1
-7 % -3 // -1
В отличие от Math.abs(x) % n, % не даёт "положительный остаток" — для этого нужна собственная реализация.
**:2 ** 3→8;2 ** -1→0.5;(-2) ** 0.5→NaN(корень из отрицательного — комплексное, не поддерживается).
Особенности чисел в JavaScript
- Все числа — 64-битные числа с плавающей точкой по стандарту IEEE 754 (тип
number), кромеBigInt. - Точность ограничена:
0.1 + 0.2 !== 0.3→true. Это следствие двоичного представления десятичных дробей. Number.MAX_SAFE_INTEGER(2⁵³ - 1) — максимальное целое, которое можно точно представить. Для больших целых —BigInt.
Сравнение =, == и ===
В JavaScript три разных оператора выглядят похоже, потому что используют символ "равно". = записывает значение, == сравнивает с приведением типов, === сравнивает без приведения. Путаница между присваиванием и сравнением — частая ошибка: if (x = 5) вместо if (x === 5).
Сводная таблица
| Свойство | = | == | === |
|---|---|---|---|
| Назначение | Записать значение в переменную или свойство | Проверить равенство с приведением типов | Проверить равенство значения и типа |
| Категория | Присваивание | Сравнение (нестрогое) | Сравнение (строгое) |
| Результат выражения | Присвоенное значение | true или false | true или false |
| Приводит типы операндов | Не применимо (не сравнивает) | Да | Нет |
| Меняет значение слева | Да | Нет | Нет |
| Слева допустимо выражение-приёмник | Да (let x, obj.key) | Нет | Нет |
| Типичное использование | const n = 10, user.name = "Анна" | null == undefined в legacy-коде | if (a === b), case в switch |
| Рекомендация в новом коде | Для записи и инициализации | Избегать | Для проверки равенства |
Операторы != и !== — отрицания == и === соответственно.
let x = 5; // присваивание: x теперь 5, выражение вернуло 5
x == "5"; // true — строка приведена к числу
x === "5"; // false — тип number и string различаются
if (x = 0) { } // присваивание 0 в x; условие ложно — почти всегда опечатка
if (x === 0) { } // сравнение — то, что обычно нужно
Практический вывод: для условий и сравнений — === (или !==); = — только когда нужно записать значение. Подробнее — присваивание и сравнение ниже.
Операторы сравнения и равенства
Сравнения делятся на строгие и нестрогие, а также на абстрактные и семантические (например, in, instanceof). Сводная таблица =, ==, === — выше.
1. Абстрактное равенство ==
Оператор == пытается привести операнды к одному типу перед сравнением. Алгоритм сложен и содержит множество специальных правил. Вот основные случаи:
null == undefined→true(единственная "честная" пара).- Число и строка: строка → число, затем числовое сравнение.
- Булево —
true→1,false→0, затем сравнение. - Объект и примитив: объект → примитив (
ToPrimitive), затем сравнение. NaN == NaN→false(всегда).
Примеры-ловушки:
0 == false // true
"" == false // true
"0" == false // true
[] == false // true ( [] → "" → 0 → false )
[0] == false // true ( [0] → "0" → 0 )
[1] == true // true ( [1] → "1" → 1 )
[1,2] == "1,2" // true
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Из-за непредсказуемости и трудностей отладки == в новом коде не используют — см. сводную таблицу.
2. Строгое равенство ===
Проверяет равенство без приведения типов:
- Если типы различаются →
false. - Для чисел:
+0 === -0→true,NaN === NaN→false. - Для строк, булевых,
null,undefined,symbol,bigint— по значению. - Для объектов — по ссылке (два объекта равны, только если это один и тот же объект в памяти).
Для сравнения NaN используется Object.is(NaN, NaN) → true, а также Object.is(+0, -0) → false.
3. Операторы неравенства — !=, !==, <, >, <=, >=
!=и!==— отрицания==и===.- Операторы
<,>и т.д. при сравнении:- Строк — лексикографически (по кодам UTF-16);
- Чисел — численно;
- Смешанных типов — приведение к числу (кроме случая, когда один из операндов — строка, а другой — объект: сначала объект → примитив, и если получилась строка — лексикография).
"2" > "10" // true (сравнение кодов: '2' > '1')
2 > "10" // false (2 > 10)
"2" > 10 // false
"12" > "2" // false — лексикография: '1' < '2'
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
4. Оператор in
Проверяет, существует ли собственное или унаследованное свойство с указанным именем в объекте.
"length" in [] // true (наследуется от Array.prototype)
"push" in [] // true
"toString" in {} // true (от Object.prototype)
"a" in { a: undefined } // true — важно: проверяется *существование*, а не значение
"a" in {} // false
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Имя свойства всегда приводится к строке. Для проверки собственных свойств — Object.hasOwn(obj, key) (ранее Object.prototype.hasOwnProperty.call).
5. Оператор instanceof
Проверяет, входит ли прототип правого операнда в цепочку прототипов левого.
[] instanceof Array // true
[] instanceof Object // true
new Date() instanceof Date // true
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на работе с созданием объектов.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Алгоритм: left instanceof right эквивалентен right[Symbol.hasInstance](left), если определён, иначе — проверке left.[[Prototype]] === right.prototype рекурсивно.
Особенности:
- Не работает между разными контекстами (например, массив из другого фрейма не будет
instanceof Arrayв текущем); - Для встроенных типов надёжнее использовать
Array.isArray(),typeofи т.д.
Логические и условные операторы
Логические операторы в JavaScript не ограничиваются булевой алгеброй: их поведение расширено до работы с любыми значениями, и они активно используются для управления потоком данных и построения безопасных выражений.
1. Логическое И — &&
Оператор && вычисляет выражения слева направо и возвращает:
- первое ложное значение (falsy), если оно встречается;
- последнее истинное значение (truthy), если все истинны.
Это короткозамкнутое вычисление (short-circuit evaluation): правый операнд вычисляется только если левый истинен.
true && "hello" // "hello"
false && expensiveFn() // false — expensiveFn() не вызывается
null && "world" // null
0 && 1 // 0
"user" && obj.name // obj.name — только если "user" истинно (всегда)
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Идиомы:
- Безопасная проверка цепочки свойств (до появления optional chaining):
const name = user && user.profile && user.profile.name;
- Выполнение побочного эффекта при условии:
isValid && console.log("Валидация пройдена");
Важно: && не приводит результат к boolean. Он возвращает значение одного из операндов, что делает его мощным инструментом для управления потоком данных, но требует осторожности в условиях, где ожидается строго true/false.
2. Логическое ИЛИ — ||
Аналогично, || возвращает:
- первое истинное значение;
- последнее ложное, если все ложны.
Короткозамкнутое: правый операнд вычисляется, только если левый ложен.
false || "default" // "default"
0 || 1 // 1
null || undefined // undefined
"name" || expensiveFn() // "name" — expensiveFn() не вызывается
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Идиомы:
- Задание значений по умолчанию (устаревшая практика для параметров):
function greet(name) {
name = name || "Гость"; // опасно: если name = 0 или "", будет "Гость"
return `Привет, ${name}`;
}
→ Сегодня предпочтительнее параметры по умолчанию: function greet(name = "Гость").
- Накопление значений:
const value = config.option || env.OPTION || DEFAULT;
3. Оператор нулевого слияния — ??
Появился в ES2020 для устранения недостатков ||. Оператор ?? возвращает правый операнд только если левый — null или undefined. В отличие от ||, он игнорирует другие ложные значения (0, "", false).
0 ?? "default" // 0
"" ?? "default" // ""
false ?? "default" // false
null ?? "default" // "default"
undefined ?? "fallback" // "fallback"
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Это позволяет безопасно задавать значения по умолчанию без нарушения семантики нуля или пустой строки.
Комбинирование с && и ||:
Приоритет ?? ниже, чем у && и ||, но выше, чем у =, += и т.д. Однако запрещено писать a || b ?? c без скобок — это вызовет синтаксическую ошибку, чтобы избежать неоднозначности.
Правильно:
(a || b) ?? c
a || (b ?? c)
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
4. Условный (тернарный) оператор — ? :
Единственный тернарный оператор: условие ? выражение1 : выражение2.
Алгоритм:
- Вычисляется условие;
- Если
ToBoolean(условие)→true, вычисляется и возвращается выражение1; - Иначе — выражение2.
Оба выражения не вычисляются заранее — действует короткое замыкание.
const status = isLoading ? "загрузка..." : data ? "готово" : "ошибка";
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Ключевое отличие от if…else: тернарный оператор — выражение, а не инструкция. Он возвращает значение и может использоваться везде, где ожидается значение — в присваивании, возврате, аргументах, шаблонных строках.
return user.isAdmin ? adminView : userView;
const message = `Счёт: ${balance >= 0 ? balance : "отрицательный"}`;
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Рекомендации:
- Избегайте вложенных тернарных операторов глубже одного уровня — это ухудшает читаемость.
- Не используйте для побочных эффектов (например,
cond ? f() : g()допустимо, ноcond ? x = 1 : y = 2— лучше черезif). - При длинных ветках — выносите в переменные или используйте
if.
Битовые и побитовые операторы
Побитовый оператор обрабатывает каждый бит 32-битного целого, а не "истину" выражения как &&/||.
Битовые операторы работают с 32-битными целыми числами со знаком в дополнительном коде (two’s complement).
1. Побитовые логические операторы
| Оператор | Название | Описание |
|---|---|---|
& | И | Возвращает 1 в бите, если оба бита = 1 |
| | ИЛИ | Возвращает 1, если хотя бы один бит = 1 |
^ | Исключающее ИЛИ | Возвращает 1, если биты различны |
~ | НЕ (уже рассмотрен) | Инвертирует все биты |
Пример:
5 & 3 // 1 — 0b101 & 0b011 = 0b001
5 | 3 // 7 — 0b101 | 0b011 = 0b111
5 ^ 3 // 6 — 0b101 ^ 0b011 = 0b110
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Применения:
- Маскирование флагов:
flags & PERMISSION_READ - Установка флагов:
flags |= PERMISSION_WRITE - Инверсия флагов:
flags ^= TOGGLE_MODE
2. Побитовые сдвиги
| Оператор | Название | Описание |
|---|---|---|
<< | Левый сдвиг | Сдвигает биты влево, заполняя нулями справа. Эквивалентно умножению на 2ⁿ (но с усечением). |
>> | Правый сдвиг со знаком | Сохраняет знак: заполняет слева старшим битом (для отрицательных — единицами). |
>>> | Правый сдвиг без знака | Всегда заполняет нулями слева. Результат — беззнаковое 32-битное целое (всегда ≥ 0). |
Примеры:
8 << 1 // 16
-8 >> 1 // -4
-8 >>> 1 // 2147483644 — интерпретируется как большое положительное число
1 << 31 // -2147483648 — переполнение в signed int
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Важно: все сдвиги работают с n % 32, то есть x << 33 эквивалентно x << 1.
Когда использовать битовые операции?
- Работа с низкоуровневыми данными (парсинг бинарных протоколов, шейдеры в WebGL);
- Оптимизация флагов (часто в играх, эмуляторах);
- Хэширование, криптографические примитивы.
В повседневной веб-разработке они редки — и их использование требует комментариев и обоснования.
Операторы присваивания
Оператор присваивания (=) — один из самых фундаментальных. Он вычисляет правый операнд, затем записывает результат в левостороннее выражение (LHS), и возвращает присвоенное значение. Отличие = от == и === — в сводной таблице.
1. Простое присваивание — =
a = b = 5; // сначала b = 5 → 5, затем a = 5 → 5
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Ассоциативность — правая, поэтому цепочки работают как ожидается.
2. Составные присваивания
Комбинируют операцию и присваивание:
| Оператор | Эквивалент |
|---|---|
+= | a = a + b |
-= | a = a - b |
*= | a = a * b |
/= | a = a / b |
%= | a = a % b |
**= | a = a ** b |
&= | a = a & b |
|= | a = a | b |
^= | a = a ^ b |
<<= | a = a << b |
>>= | a = a >> b |
>>>= | a = a >>> b |
Особенность: левый операнд вычисляется один раз, что важно при работе со свойствами:
obj.prop += 1;
// эквивалентно:
// let temp = obj;
// temp.prop = temp.prop + 1;
// (а не obj.prop = obj.prop + 1 — obj не вычисляется дважды)
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Это предотвращает ошибки при изменении obj между обращениями.
3. Деструктурирующее присваивание
Позволяет извлекать данные из массивов и объектов в переменные по шаблону.
Деструктуризация массива:
const [first, second, ...rest] = [10, 20, 30, 40];
// first = 10, second = 20, rest = [30, 40]
const [x, , y] = [1, 2, 3]; // пропуск элемента: x = 1, y = 3
const [a = 1, b = 2] = [undefined, 3]; // a = 1 (по умолчанию), b = 3
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Деструктуризация объекта:
const { name, age: years, active = true } = { name: "Тимур", age: 30 };
// name = "Тимур", years = 30, active = true
const { length } = "привет"; // length = 6 — работает с любым итерируемым/объектом
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Вложенные шаблоны:
const {
user: { name, role: { title } },
settings: { theme = "light" }
} = response;
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Деструктуризация в параметрах функции:
function draw({ x = 0, y = 0, color = "black" } = {}) {
// ...
}
draw({ x: 10, color: "red" });
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Обмен значений без временной переменной:
[a, b] = [b, a];
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Ограничения:
- Левая часть должна быть корректным шаблоном деструктуризации;
- При несовпадении структуры —
undefined(если нет значения по умолчанию); - Ошибки при попытке присвоить
undefinedилиnullв деструктуризацию объекта (например,const { x } = null→TypeError).
Деструктуризация — отдельный механизм, интегрированный в ядро языка. Она компилируется в последовательность операций доступа к свойствам и присваиваний, и её производительность сравнима с ручным извлечением.
Операторы расширения (...) и остатка
Синтаксис ... (три точки) используется в двух принципиально разных, но внешне похожих контекстах: как расширение (spread) и как остаток (rest). Их различие определяется положением в выражении.
1. Расширение (Spread)
Оператор расширения извлекает элементы из итерируемого объекта (массива, строки, Set, Map, генератора и т.д.) и "распыляет" их в месте использования. Контексты применения:
a) В литералах массивов
const a = [1, 2];
const b = [0, ...a, 3]; // [0, 1, 2, 3]
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
— создаёт новый массив, копируя элементы из a. Это мелкая копия (shallow copy).
b) В литералах объектов (начиная с ES2018)
const defaults = { theme: "light", lang: "ru" };
const config = { ...defaults, lang: "en" }; // { theme: "light", lang: "en" }
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
— копирует собственные перечисляемые свойства из defaults в новый объект. При совпадении ключей позже указанные свойства перекрывают более ранние.
Особенности объектного spread:
- Не вызывает геттеры — читает значения напрямую;
- Не копирует символы, если они не перечисляемы;
- Не копирует прототип, не вызывает конструктор — результат всегда "плоский"
Object; - При конфликтах — побеждает последнее свойство:
{ ...{a:1}, a:2 }→{a:2}.
c) В вызовах функций
Math.max(...[10, 20, 30]); // эквивалентно Math.max(10, 20, 30)
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
— распаковывает итерируемый объект в список аргументов. Это замена Function.prototype.apply.
d) В строках и других итерируемых
[..."hello"] // ['h','e','l','l','o']
new Set(...[1, 1, 2]) // Set {1, 2}
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на работе с созданием объектов.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Важные ограничения:
- Spread работает только с итерируемыми объектами (
Symbol.iteratorдолжен быть определён).{a:1}— не итерируемый, поэтому...{a:1}в массиве вызовет ошибку (но в объекте — разрешено, т.к. объектный spread использует другой механизм —Object.assign-подобный). - Spread не работает в левой части присваивания — там требуется rest.
2. Остаток (Rest)
Оператор остатка собирает неиспользованные элементы в новый массив или новый объект. Применяется в:
a) Параметрах функции
function sum(first, ...rest) {
return rest.reduce((a, b) => a + b, first);
}
sum(1, 2, 3, 4); // 10
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на работе с методами коллекций.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
— rest получает все аргументы, начиная со второго, в виде массива.
b) Деструктуризации массива
const [head, ...tail] = [1, 2, 3, 4]; // head = 1, tail = [2, 3, 4]
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
— tail — новый массив, содержащий оставшиеся элементы.
c) Деструктуризации объекта (ES2018+)
const { name, ...meta } = { name: "Тимур", age: 30, city: "Уфа" };
// name = "Тимур", meta = { age: 30, city: "Уфа" }
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
— meta получает все остальные собственные перечисляемые свойства, кроме name.
Ключевые различия между spread и rest:
| Критерий | Spread (...x) | Rest (...x) |
|---|---|---|
| Контекст | Правая часть, литералы, вызовы | Левая часть, параметры, деструктуризация |
| Действие | Распаковывает | Собирает |
| Результат | Множество значений/свойств | Один массив/объект |
| Можно использовать в одном выражении? | Да, несколько раз: [...a, ...b] | Только один раз на уровень деструктуризации: [a, ...rest] — OK; [...x, ...y] — ошибка |
Производительность и семантика:
- Оба оператора создают новые структуры данных — копирование происходит при каждом использовании.
- Spread в объектах не вызывает сеттеры — присваивание идёт напрямую.
- Rest в объектах не включает не перечисляемые свойства и символы (если не перечисляемы).
Оператор запятой ,
Оператор запятой — один из самых редко используемых, но принципиально важных. Он вычисляет оба операнда слева направо и возвращает значение правого операнда.
let a, b;
a = (1, 2, 3); // a = 3
b = (console.log("A"), console.log("B"), 42); // выведет A, B; b = 42
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Особенности:
- Низший приоритет среди всех операторов — ниже, чем присваивание.
- Используется в заголовках циклов
for, где допустимы три выражения, разделённые запятыми:
for (let i = 0, j = 10; i < j; i++, j--) { ... }
- Применяется в минифицированном коде, макросах (например, в Babel-плагинах), и при необходимости выполнить побочные эффекты в выражении (например, в
return,throw,yield).
Не путать с:
- Запятой в литералах массивов/объектов — это разделитель элементов, не оператор;
- Запятой в объявлениях переменных (
let a, b) — синтаксис объявления, не выражение.
Пример использования в return:
function f() {
let x = 0;
return (x++, x * 2); // сначала инкремент, затем возврат x*2
}
f(); // 2
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Хотя синтаксис корректен, чрезмерное использование оператора запятой ухудшает читаемость. Его применение оправдано только в узких технических сценариях.
Условные конструкции — if…else, switch
До сих пор мы говорили об выражениях (x ? a : b), которые возвращают значение. Теперь перейдём к инструкциям — конструкциям управления потоком, которые не возвращают значения и не могут использоваться в правой части присваивания.
1. if…else
Классическая конструкция ветвления. Синтаксис:
if (выражение) {
// блок, выполняемый если ToBoolean(выражение) === true
} else if (выражение2) {
// ...
} else {
// по умолчанию
}
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на работе с условной логикой.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Семантические детали:
- В скобках после
ifдолжно быть выражение (любое), которое будет приведено к булеву значению. - Фигурные скобки
{ }необязательны для однострочных блоков, но их отсутствие считается антипаттерном (ошибки при добавлении строк, проблемы сelseв "висячем" виде). elseсвязывается с ближайшимif, не имеющимelse— что может привести к неочевидному поведению при неправильной расстановке скобок.
Рекомендации:
- Всегда использовать фигурные скобки;
- Избегать "висячих"
else; - Для простых случаев — предпочитать тернарный оператор или логические операторы (если нужен результат);
- Для множества условий — рассмотреть
switchили объект-карту.
2. switch
Конструкция выбора, предназначенная для сравнения одного значения с множеством возможных вариантов.
switch (выражение) {
case значение1:
// код
break;
case значение2:
// код
break;
default:
// по умолчанию
}
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Как это работает:
- Вычисляется выражение (селектор);
- Последовательно сравнивается со значениями в
caseчерез строгое равенство (===); - При совпадении — начинается выполнение с этого
case; - Выполнение продолжается до первого
break,return,throwили концаswitch; - Если совпадений нет — выполняется
default(если есть).
Поведение без break — fall-through:
switch (status) {
case "pending":
log("В обработке");
case "approved": // ← выполнится, даже если status === "pending"
log("Одобрено");
break;
}
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Это осознанная возможность — например, для объединения нескольких кейсов:
case "mon":
case "tue":
case "wed":
console.log("Рабочий день");
break;
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Что можно использовать в case:
- Любые выражения, вычисляемые в момент разбора
switch(но не динамически при каждом проходе):
const A = 1, B = 2;
switch (x) {
case A + B: // OK, вычисляется один раз при входе в switch
}
- Выражения не могут быть объектами, массивами — сравнение через
===сделает их различными.
Ограничения switch:
- Не поддерживает диапазоны (
case 1..10:— нет); - Не поддерживает условия (
case x > 5:— нет); - Чувствителен к типам (
switch (1) { case "1": ... }не сработает).
Альтернативы:
- Объект-карта:
const handlers = { "mon": fn1, "tue": fn2 }; handlers[day]?.(); - Массив с индексацией;
if…else if— для сложных условий.
Приоритеты операторов
Приоритет определяет, какие операторы вычисляются первыми в выражении без скобок. Ассоциативность — порядок вычисления операторов с одинаковым приоритетом (слева направо или справа налево).
Ниже — сокращённая, но практическая таблица приоритетов (от высшего к низшему), сгруппированная по смыслу. Полная таблица содержит 21 уровень — для повседневного использования достаточно помнить ключевые группы.
| Уровень | Операторы / конструкции | Ассоциативность | Комментарий |
|---|---|---|---|
| 21 | . [] () new (без аргументов) | левая | Доступ к свойствам, вызов, создание |
| 20 | new (с аргументами), ... (spread) | правая / нет | new Foo(), ...arr |
| 19 | ++ -- (постфиксные) | левая | x++ |
| 18 | ++ -- (префиксные), + - ! ~ typeof void delete await | правая | Унарные операторы |
| 17 | ** | правая | Возведение в степень |
| 16 | * / % | левая | Арифметика |
| 15 | + - (бинарные) | левая | Сложение/вычитание (и конкатенация) |
| 14 | << >> >>> | левая | Побитовые сдвиги |
| 13 | < <= > >= in instanceof | левая | Сравнения |
| 12 | == != === !== | левая | Равенство |
| 11 | & | левая | Побитовое И |
| 10 | ^ | левая | Побитовое XOR |
| 9 | | | левая | Побитовое ИЛИ |
| 8 | && | левая | Логическое И |
| 7 | || | левая | Логическое ИЛИ |
| 6 | ?? | левая | Нулевое слияние |
| 5 | ? : | правая | Тернарный оператор |
| 4 | = += -= и все составные присваивания | правая | Присваивание |
| 3 | yield yield* | правая | Генераторы |
| 2 | , (оператор запятой) | левая | Последовательное вычисление |
| 1 | => (стрелочные функции) | правая | Только при многострочном теле |
Практические правила чтения выражений:
- Сначала — вызовы и доступы:
obj.method()[0].prop— сначалаobj.method(), затем[0], затем.prop. - Унарные — сильнее бинарных:
!a + b→(!a) + b, а не!(a + b). **— правоассоциативен:2 ** 3 ** 2→2 ** (3 ** 2)=512, а не(2 ** 3) ** 2=64.&&и||не смешиваются без скобок с??:a || b ?? c— синтаксическая ошибка (намеренно).- Тернарный — правоассоциативен:
a ? b : c ? d : e→a ? b : (c ? d : e).
Рекомендации:
- Не полагайтесь на память приоритетов — используйте скобки для явного указания порядка, особенно при смешивании разных групп (
==,&&,??,? :); - В IDE — включите подсветку расстановки скобок (например, в VS Code:
Editor: Bracket Pair Colorization); - При рефакторинге — не удаляйте "лишние" скобки без проверки семантики.
Практика чтения выражений
Если выражение становится длинным, лучше сначала сделать его понятным, и только потом "красивым". В промышленном коде читаемость почти всегда важнее компактности.
Плохо (трудно читать):
const result = user && user.profile && user.profile.balance > 0 ? user.profile.balance : 0;
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Лучше:
const balance = user?.profile?.balance ?? 0;
const result = balance > 0 ? balance : 0;
Разбор:
- Фрагмент показывает рабочий паттерн JavaScript и его структуру от объявления до итогового действия.
- Сначала интерпретатор обрабатывает объявления переменных, функций и выражений, формируя контекст выполнения.
- Затем код исполняется сверху вниз: каждое выражение использует уже вычисленные значения и обновляет текущее состояние.
- Ключевые операторы и методы в примере управляют логикой ветвления, преобразованием данных и вызовами функций.
- В примере акцент сделан на пошаговом выполнении кода.
- Порядок выполнения важен — сначала инициализация, потом основная обработка, затем получение и вывод результата.
- Итог работы блока — конкретный эффект: возвращаемое значение, изменение данных или вывод в консоль.
- Такой разбор помогает быстро перенести шаблон в реальный код и избежать ошибок в последовательности шагов.
Короткий чеклист:
- смешиваете
&&,||,??— ставьте скобки явно; - есть побочные эффекты — выносите в отдельные строки;
- сложный тернарный оператор — заменяйте на
if/else.
Связанные темы: