Логические операторы присваивания (||=,
&&=, ??=) объединяют поведение
логических операций и операции присваивания, позволяя изменять значение
переменной только при выполнении определённого условия. В экосистеме
JavaScript они относятся к современным возможностям языка (ES2021), а
при использовании SWC часто становятся объектом трансформации для
обеспечения совместимости с более старыми окружениями.
Каждый из операторов опирается на принцип короткого замыкания (short-circuit evaluation), что напрямую влияет на поведение присваивания.
||=
Оператор логического ИЛИ с присваиванием:
a ||= b;
Эквивалентен:
a || (a = b);
Поведение:
a является truthy, присваивание не
выполняется
a является falsy, a получает
значение b
Примеры:
let a = 0;
a ||= 10; // 10
let b = 5;
b ||= 10; // 5
&&=
Оператор логического И с присваиванием:
a &&= b;
Эквивалентен:
a && (a = b);
Поведение:
a falsy — присваивание не происходит
a truthy — a получает значение
b
Примеры:
let a = 1;
a &&= 10; // 10
let b = 0;
b &&= 10; // 0
??=
Оператор нулевого слияния с присваиванием:
a ??= b;
Эквивалентен:
a ?? (a = b);
Поведение:
a равен
null или undefined
||=, учитываются только nullish-значения
Примеры:
let a = 0;
a ??= 10; // 0
let b = null;
b ??= 10; // 10
SWC (@swc/core) является
высокопроизводительным компилятором JavaScript/TypeScript, написанным на
Rust. Он выполняет трансформации синтаксиса на этапе компиляции, включая
преобразование логических операторов присваивания в эквивалентный
ES5-совместимый код при необходимости.
Трансформация особенно важна для:
При включённой трансформации SWC преобразует:
a ||= b;
в примерно:
a || (a = b);
a &&= b;
в:
a && (a = b);
a ??= b;
в:
a ?? (a = b);
Важно, что SWC сохраняет семантику короткого замыкания, не вычисляя правую часть без необходимости.
Настройка трансформаций выполняется через .swcrc:
{
"jsc": {
"parser": {
"syntax": "ecmascript"
},
"target": "es5"
},
"env": {
"targets": "> 0.25%, not dead"
}
}
При указании старого target, SWC автоматически включает
необходимые трансформации, включая логические операторы присваивания.
Дополнительно поведение может зависеть от комбинации:
jsc.target
env.targets
||= и ??=
Ключевая ошибка при миграции и трансформации заключается в путанице между truthy/falsy и nullish логикой.
| Оператор | Условие срабатывания | ||
|---|---|---|---|
| | =
|
falsy (0, ““, false,
null, undefined, NaN)
|
||
??=
|
только null и undefined
|
SWC строго сохраняет это различие при транспиляции, не унифицируя поведение.
Логические операторы присваивания выполняют правую часть только при необходимости, что критично для выражений с побочными эффектами:
let a = 1;
a ||= console.log("executed");
Если a truthy, console.log не вызовется.
SWC обязан сохранять это поведение при трансформации, что влияет на генерацию AST и оборачивание выражений в условные конструкции.
В SWC данные операторы представлены в AST как
AssignmentExpression с оператором:
||=
&&=
??=
Упрощённая структура:
{
"type": "AssignmentExpression",
"operator": "||=",
"left": { "type": "Identifier", "value": "a" },
"right": { "type": "NumericLiteral", "value": 10 }
}
При трансформации AST переписывается в форму:
a || (a = 10)
что уже представляется как комбинация LogicalExpression и
AssignmentExpression.
Логические операторы присваивания могут взаимодействовать с:
?.)
Комбинации требуют аккуратной трансформации:
obj.prop ||= 1;
obj?.prop ||= 1;
Во втором случае SWC должен сохранить защиту от null.
При минификации SWC (через minify) выражения могут быть
дополнительно упрощены, но семантика не меняется. Например:
a || (a = b)
может быть сжато по пробелам, но не по структуре.
При использовании @swc/core с TypeScript парсером
логические операторы присваивания обрабатываются на уровне синтаксиса
без дополнительной типовой логики. Ошибки типов не влияют на
трансформацию.
config.timeout ||= 5000;
SWC преобразует это безопасно для старых рантаймов.
options.retries ??= 3;
state.loaded &&= checkIntegrity(state);
Разница ||= и ??= часто становится источником
логических ошибок после компиляции.
Если правая часть содержит вызовы функций, важно помнить о ленивом вычислении:
value ||= expensiveCall();
SWC не изменяет порядок вычисления, но при рефакторинге это может быть нарушено вручную.
a.b ||= c.d ||= getValue();
Такие конструкции транслируются в вложенные логические выражения, что может усложнить дебаг после компиляции.
SWC может по-разному обрабатывать операторы в зависимости от
target:
es2021 и выше — трансформация не выполняется
es2018 и ниже — выполняется полная транспиляция
es5 — всегда преобразуется в логические выражения с
присваиванием
SWC ориентирован на высокую скорость трансформации, поэтому:
Это делает SWC особенно эффективным в больших монорепозиториях, где подобные конструкции встречаются массово и требуют быстрых сборок.