Найти в Дзене
Журнал «Код»

Что означают три точки в JavaScript

Лайфхак, когда мы не знаем точно, сколько будет аргументов или параметров у функции Во вчерашней статье про сортировку слиянием мы использовали такой код в конце функции: return [ ...arr, ...left, ...right ] Судя по квадратным скобкам, мы возвращаем массив, но в нём творится что-то странное: перед каждым элементом стоят точки, да ещё каждый из этих элементов тоже массив. Рассказываем, как такое возможно и что здесь делают три точки. Кратко главное Простой пример. У нас есть массив problems = ['сессия', 'отчет', 'здоровье']. Если просто сказать console.log(problems), то выведется целый объект (как бы в обёртке), и работать с ним дальше нужно именно как с объектом: console.log(problems) > (3) ['сессия', 'отчет', 'здоровье'] Если нам не нужен объект, а нужно просто посмотреть на значения подряд, то делаем так: console.log(...problems) > сессия отчет здоровье А теперь наоборот. Допустим нам нужна функция, которая разом решает все проблемы, но мы не знаем, сколько этих проблем будет. Тогда
Оглавление

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

Во вчерашней статье про сортировку слиянием мы использовали такой код в конце функции:

return [ ...arr, ...left, ...right ]

Судя по квадратным скобкам, мы возвращаем массив, но в нём творится что-то странное: перед каждым элементом стоят точки, да ещё каждый из этих элементов тоже массив. Рассказываем, как такое возможно и что здесь делают три точки.

Кратко главное

  • Конкретно в этом случае три точки — это оператор расширения.
  • Он «разбивает» объект на набор его элементов и отдаёт их по порядку.
  • Можно представить, что если объект — это набор чего-то в обёртке, то оператор расширения надрывает эту обёртку, и из объекта всё высыпается.
  • Оператор можно использовать и наоборот: собрать массу каких-то значений в один объект.

Простой пример. У нас есть массив problems = ['сессия', 'отчет', 'здоровье']. Если просто сказать console.log(problems), то выведется целый объект (как бы в обёртке), и работать с ним дальше нужно именно как с объектом:

console.log(problems) > (3) ['сессия', 'отчет', 'здоровье']

Если нам не нужен объект, а нужно просто посмотреть на значения подряд, то делаем так:

console.log(...problems) > сессия отчет здоровье

А теперь наоборот. Допустим нам нужна функция, которая разом решает все проблемы, но мы не знаем, сколько этих проблем будет. Тогда этот оператор примет любое количество значений и соберёт их в один объект:

function solve(...allProblems){ }

Теперь эта функция примет любое число значений и уложит их в общий массив allProblems.

Оператор расширения

Три точки в JavaScript имеют два значения: они обозначают остаточные параметры или работают как оператор расширения. В нашем примере с функцией это как раз оператор расширения, поэтому начнём с него.

Смысл оператора расширения — преобразовать объект в перечислимый список. При этом сам объект тоже должен содержать значения, которые можно посчитать и к которым можно обратиться по отдельности. Например, это может быть массив — можно перечислить по очереди всё его содержимое. Или это может быть строка — мы можем перебрать в ней каждый символ.

На практике это может работать так. Допустим, у нас есть массив с числами, и нам нужно найти наибольшее из них:

var a = [2,7,3, 5, 4];

Но если мы используем обычную команду поиска максимума Math.max(a), то ничего не выйдет: ей нужно несколько чисел, а не один большой объект:

Null, ноль и Undefined: разбираемся в сортах пустоты
Null, ноль и Undefined: разбираемся в сортах пустоты

Чтобы обойти это ограничение, используют оператор расширения — он сделает из массива отдельные значения, которые будут использоваться как параметры. В этом случае вызов команды будет выглядеть так: Math.max(...a)

-3

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

Вернёмся к нашему примеру:

return [ ...arr, ...left, ...right ]

Теперь, зная как работает оператор расширения, мы понимаем, что функция возвращает массив (потому что квадратные скобки), который собирается из трёх частей:

  1. Сначала в массив войдут все элементы массива arr (а не сам массив).
  2. Потом все элементы массива left.
  3. И напоследок — все элементы массива right.

Самое интересное, что если какой-то элемент окажется пустым, то от него не войдёт ничего. Вот как это работает на практике: допустим, у нас есть три массива:

  • в arr будет лежать [2,7,0];
  • массив left будет пустым;
  • а в right — [1,2].

Тогда команда return [ ...arr, ...left, ...right ] вернёт такой массив: [2,7,0,1,2].

Остаточные параметры

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

Допустим, у нас есть функция, которая складывает переданные ей параметры и возвращает сумму:

function s(a, b) { return a + b; }

JavaScript

Copy

Но эта функция может работать только с двумя параметрами: если ей передать три, то она отбросит лишние и не будет их учитывать при расчётах:

-4

А вот с помощью остаточных параметров мы можем собрать все аргументы вместе в один массив, а потом просто перебрать его и найти сумму всех значений:

function s(...args) { // тут будет храниться промежуточная сумма let sum = 0; // перебираем все элементы массива args и добавляем их к сумме for (let arg of args) sum += arg; // возвращаем сумму
return sum; }
console.log(s(2,4,6,8,10))

JavaScript

Copy

-5

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