Какова временная сложность синтаксиса распространения JavaScript в массивах?

Мне было интересно, какова временная сложность использования распространения с массивом в JavaScript. Это линейный O (n) или постоянный O (1)?

Пример синтаксиса ниже:

let lar = Math.max(...nums)

person Jaaayz    schedule 15.07.2019    source источник
comment
У меня нет никаких доказательств, но было бы довольно странно, если бы не O(n). Он должен перебирать каждый элемент массива.   -  person jhpratt    schedule 15.07.2019
comment
Оператора спреда нет, есть спред синтаксис. ;-)   -  person RobG    schedule 15.07.2019
comment
@RobG извини за это. Отредактирую вопрос :)   -  person Jaaayz    schedule 15.07.2019
comment
@jhpratt да, по крайней мере, лучше увидеть более четкую картину, поэтому я и спросил, ха-ха.   -  person Jaaayz    schedule 15.07.2019
comment
Я думаю, это будет зависеть от альтернативы, с которой вы хотите сравнить, и от реализации, в которой она работает, например. в OP против Math.max.apply(null,nums) и, возможно, в случае хост-объекта против Array.from(document.getElementsByTagName('p')) или подобного.   -  person RobG    schedule 15.07.2019


Ответы (1)


Spread вызывает свойство [Symbol.iterator] рассматриваемого объекта. Для массивов это будет перебирать каждый элемент в массиве, вызывая .next() итератора массива до тех пор, пока итератор не будет исчерпан, что приведет к сложности O(N).

По той же самой причине циклы for..of (которые также вызывают [Symbol.iterator]) также являются O(N):

const arr = [1, 2, 3];
for (const item of arr) {
  console.log(item);
}

В качестве живого примера посмотрите, как следующий фрагмент кода занимает некоторое время для выполнения:

const arr = new Array(3e7).fill(null);
const t0 = performance.now();
const arr2 = [...arr];
console.log(performance.now() - t0);

(если бы операция была O(1), она была бы почти мгновенной, но это не так)

Распространение аргумента отличается от распространения массива, но в нем используется одна и та же операция (повторяет итерацию до тех пор, пока она не будет исчерпана), и поэтому имеет ту же сложность.

Для вызовов функций:

myFunction(...iterableObj);
person CertainPerformance    schedule 15.07.2019
comment
Просто отметим, что упрощенные тесты производительности, подобные приведенным выше, вероятно, сильно зависят от того, как различные реализации оптимизируют или не оптимизируют код. Внесение изменений в выполняемые операции может оказать значительное влияние на относительную производительность, которая намного превосходит любые различия в ..., for..in, for..of и т. д. :-) - person RobG; 15.07.2019