Перетяжка, Премия ТПрогер, 13.11
Перетяжка, Премия ТПрогер, 13.11
Перетяжка, Премия ТПрогер, 13.11

JavaScript: как логические операторы присваивания упрощают код и повышают читаемость

156 открытий2К показов
JavaScript: как логические операторы присваивания упрощают код и повышают читаемость

Это перевод статьи Мэта Смитта (Matt Smith) — веб-разработчика, фронтенд-инженера и UX-дизайнера.

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

Именно здесь на помощь приходят логические операторы присваивания — компактное нововведение стандарта ES2021, которое позволяет сократить типичные условные конструкции, не меняя при этом саму логику кода.

Что такое логические операторы присваивания?

Логические операторы присваивания объединяют обычный логический оператор (||, && или ??) с оператором присваивания (=), создавая короткую и наглядную запись.

По сути, это синтаксический сахар, позволяющий писать условное присваивание в одну строку. При этом они работают по тому же принципу, что и обычные логические выражения: правая часть вычисляется только в том случае, если левая не проходит логическую проверку — то есть оказывается falsy, truthy или nullish (в зависимости от конкретного оператора).

Примечание: Оператор опциональной последовательности (?.) нельзя использовать в левой части логического присваивания.

Попытка сделать это приведёт к синтаксической ошибке:

			// ❌ SyntaxError:
user?.settings ||= {};
		

Если нужно безопасно присвоить значение, используйте обычную проверку или промежуточную переменную:

			if (user?.profile == null) {
  user.profile = {};
}
		

Оператор опциональной последовательности (?.) возвращает значение свойства, а не ссылку на само свойство.

А поскольку в JavaScript присваивание возможно только в том случае, если левая часть выражения является ссылкой (например, переменной или свойством объекта), использование ?. в левой части делает выражение некорректным.

Логическое присваивание через OR (||=)

Оператор ||= выполняет присваивание только тогда, когда значение слева является ложным (falsy) — то есть false, 0, “”, null, undefined или NaN.

Присвоить, если значение — falsy.

			user.theme ||= 'light';
		

Это эквивалент записи:

			if (!user.theme) {
  user.theme = 'light';
}
		

Этот оператор удобен, чтобы задать значение по умолчанию, если переменная ещё не инициализирована. Однако он перезаписывает такие значения, как 0, ” или false, даже если они были установлены специально.

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

Логическое присваивание через AND (&&=)

Присвоить, если значение — truthy:

			user.isLoggedIn &&= checkPermissions(user);
Это эквивалентно:
if (user.isLoggedIn) {
  user.isLoggedIn = checkPermissions(user);
}
		

Этот оператор полезен, когда нужно обновить значение только при наличии уже существующего truthy значения.

Примечание: при использовании &&= правая часть выражения вычисляется только если левая часть является truthy, и результат этого вычисления присваивается, даже если он окажется falsy.

			let isEnabled = true;
isEnabled &&= false;
console.log(isEnabled); // false
		

Исходное значение (true) играет роль «ворот»: именно оно определяет, выполняется ли присваивание.

Однако новое значение берётся из результата вызова checkPermissions (или любого выражения справа).

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

Присваивание через nullish-оператор (??=)

Присвоить, если значение — null или undefined:

			settings.timeout ??= 3000;
		

Эквивалентно:

			if (settings.timeout === null || settings.timeout === undefined) {
  settings.timeout = 3000;
}
		

Используйте ??=, когда нужно задать значение только если переменная действительно отсутствует — то есть равна null или undefined, а не просто falsy. В отличие от ||=, этот оператор сохраняет корректные значения, такие как 0, false и ”.

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

Значения по умолчанию для пропсов компонентов

Логические операторы присваивания особенно удобны при работе с пропсами в компонентах.

Например, если часть значений не передана, можно задать дефолты прямо в коде:

			props.title ||= 'Untitled';
props.visible ??= true;
props.theme &&= props.theme.toLowerCase();
		

Такой подход:

  • делает код компактнее и читаемее,
  • избавляет от лишних if или тернарных выражений,
  • позволяет контролировать поведение пропсов при разных типах значений (null, undefined, false, ”).

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

			// Устанавливаем значение по умолчанию, если пропс не задан
props.showHelpText ??= true;

// Не перезаписываем значение, если оно уже определено
config.apiBase ||= '/api/v1';

// Избегаем присвоения null или undefined — обрабатываем только при наличии значения
formData.username &&= formData.username.trim();
		

Важно учитывать

  • Оператор ||= срабатывает, когда левая часть — falsy-значение (0, ”, false, null, undefined). Это может привести к нежелательному перезаписыванию:
			let count = 0;
count ||= 10; // значение count перезапишется на 10 — будьте внимательны
		
  • Используйте ??= если нужно проверять только на null или undefined, сохраняя корректные falsy-значения (0, ”, false).
  • Правая часть вычисляется только при необходимости, что сохраняет производительность и предотвращает побочные эффекты:
			config.apiKey ||= fetchApiKey(); 
// fetchApiKey() выполнится только если apiKey имеет falsy-значение
		

Пример с побочным эффектом

			let calls = 0;
let obj = { val: 0 };

obj.val ||= ++calls;
console.log(obj.val); // 1, потому что 0 — falsy

obj.val ||= ++calls;
console.log(obj.val); // остаётся 1, второй инкремент не выполняется
		

В этом примере:

  • Изначально obj.val равно 0, что является falsy. Поэтому выражение ++calls вычисляется и присваивается obj.val.
  • После первой строки obj.val становится 1 (truthy).
  • На второй строке условие уже не выполняется, и ++calls не вызывается.

В результате значение calls остаётся равным 1, потому что вторая операция не выполняет инкремент.

Поддержка браузерами

Логические операторы присваивания поддерживаются всеми современными окружениями:

✅ Chrome 85+, Firefox 79+, Safari 14+, Edge 85+

✅ Node.js 15+

❌ Internet Explorer — не поддерживается

Если нужно обеспечить работу в старых окружениях, используйте транспайлер, например, @babel/preset-env с настройками ES2021.

Теперь вы готовы!

Логические операторы присваивания — небольшое, но очень полезное дополнение к JavaScript. Они делают код понятнее, уменьшают шаблонные конструкции и упрощают условную логику.

Особенно полезны они во фронтенд-разработке, например:

  • при работе с props и state;
  • при задании значений по умолчанию для API;
  • при очистке и валидации форм.

Если вы уже уверенно используете ||, && и ??, переход на ||=, &&= и ??= будет естественным — здесь всё дело лишь в привычке.

Следите за новыми постами
Следите за новыми постами по любимым темам
156 открытий2К показов