Операторы spread и rest являются частью современного синтаксиса JavaScript и активно используются для работы с массивами, объектами и параметрами функций. В экосистеме SWC (Speedy Web Compiler) эти конструкции проходят стадию трансформации, обеспечивая совместимость с более старыми средами выполнения и сохраняя при этом высокую скорость компиляции.
Spread-оператор (…) используется для «разворачивания»
итерируемых структур или объектов в местах, где ожидаются отдельные
элементы.
const a = [1, 2];
const b = [3, 4];
const result = [...a, ...b];
В этом случае массивы a и b разворачиваются в
последовательность элементов, формируя новый массив.
Эквивалентная логика без spread:
const result = a.concat(b);
Spread в массивах также применяется для копирования:
const original = [1, 2, 3];
const copy = [...original];
В объектах spread позволяет копировать и объединять свойства:
const base = { a: 1, b: 2 };
const extended = { ...base, c: 3 };
Поверхностное копирование сохраняет только первый уровень вложенности.
Особенность поведения при конфликте ключей:
const a = { x: 1 };
const b = { x: 2 };
const merged = { ...a, ...b };
Значение из b перезапишет значение из a.
Rest-параметры позволяют собирать неопределённое количество аргументов в массив.
function sum(...args) {
return args.reduce((acc, n) => acc + n, 0);
}
Внутри функции args становится полноценным массивом.
Пример вызова:
sum(1, 2, 3, 4);
Rest-параметр всегда находится в конце списка параметров:
function fn(a, b, ...rest) {}
Rest также применяется при деструктуризации массивов и объектов.
const [first, ...rest] = [1, 2, 3, 4];
first получает первый элемент, rest —
оставшиеся.
const { a, ...others } = { a: 1, b: 2, c: 3 };
Переменная others содержит объект без свойства
a.
SWC — высокопроизводительный компилятор JavaScript, написанный на Rust. Он выполняет трансформацию современного синтаксиса в совместимый ES5/ES2015 код.
Spread и rest относятся к синтаксическим конструкциям, которые часто требуют преобразования в более старые выражения.
Функции с rest-параметрами преобразуются в код, где используется объект
arguments.
Исходный код:
function fn(...args) {
return args;
}
После трансформации SWC:
function fn() {
var args = Array.prototype.slice.call(arguments);
return args;
}
При наличии фиксированных параметров:
function fn(a, b, ...args) {
return args;
}
Трансформация:
function fn(a, b) {
var args = Array.prototype.slice.call(arguments, 2);
return args;
}
Здесь индекс 2 указывает на начало rest-части.
Spread в массивах часто преобразуется в concat или
вспомогательные функции.
const arr = [...a, ...b];
Возможный результат компиляции:
var arr = [].concat(a, b);
При более сложных выражениях SWC может использовать временные переменные для сохранения порядка вычислений:
const arr = [...getA(), 2, ...getB()];
Может быть преобразовано в:
var _a = getA(), _b = getB();
var arr = [].concat(_a, [2], _b);
Object spread не имеет прямого аналога в ES5, поэтому SWC использует
вспомогательные функции, аналогичные Object.assign.
const obj = { ...a, b: 2 };
Трансформация:
var obj = Object.assign({}, a, { b: 2 });
Если включена более строгая совместимость, SWC может генерировать хелпер-функции:
function _extends() {
return (_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
}).apply(this, arguments);
}
var obj = _extends({}, a, { b: 2 });
При компиляции деструктуризации SWC генерирует код, исключающий перечисленные свойства из исходного объекта.
const { a, ...rest } = obj;
Трансформация:
var a = obj.a;
var rest = {};
for (var key in obj) {
if (key !== "a" && Object.prototype.hasOwnProperty.call(obj, key)) {
rest[key] = obj[key];
}
}
В более оптимизированных режимах может использоваться вспомогательная функция для исключения свойств.
Spread-операторы сохраняют порядок вычисления выражений. SWC учитывает это при генерации промежуточных переменных.
const result = [...fn1(), ...fn2()];
Компиляция:
var _fn = fn1();
var _fn2 = fn2();
var result = [].concat(_fn, _fn2);
Такой подход предотвращает повторные вызовы функций и сохраняет корректный порядок выполнения.
SWC применяет несколько стратегий для повышения эффективности:
concat вместо ручных циклов для массивов;
Object.assign, если доступен;
Некоторые случаи spread и rest требуют более сложной обработки:
SWC стремится сохранять поведение спецификации ECMAScript, но при этом ориентируется на баланс между точностью и скоростью компиляции.
При выборе целевой версии JavaScript SWC адаптирует трансформации:
Выбор target влияет на глубину генерируемого кода и количество вспомогательных функций.
Spread и rest часто комбинируются с другими синтаксическими преобразованиями:
В таких случаях SWC строит цепочку преобразований, где spread/rest может быть обработан как на раннем, так и на позднем этапе, в зависимости от конфигурации плагинов и пресетов.