При типичном использовании JavaScript метод «push», как правило, быстрее, чем «concat», когда речь идет о добавлении элементов в массив. Тем не менее, есть краевые случаи и конкретные контексты, где «concat» может быть быстрее или более выгодным. Понимание их требует подробного взгляда на внутреннюю работу, модели использования, поведение распределения памяти и конкретные случаи использования обоих методов.
`push 'добавляет элементы в существующий массив, расширяя его на месте. Это изменяет исходный массив, добавляя новые элементы. Поскольку «push» работает над существующим массивом, он обычно избегает создания новых массивов и дополнительных накладных расходов памяти. `push 'может принимать несколько аргументов, и при использовании с` Apply` (например, `array.prototype.push.apply (arr1, arr2)`), он может эффективно добавить все элементы одного массива к другому. Этот мутационный подход, как правило, очень быстрый, потому что он избегает создания и копирования.
С другой стороны, «Concat» не мутирует оригинальный массив, но возвращает новый массив, который содержит комбинированные элементы исходного массива и добавленные значения. Поскольку `concat 'создает новый массив, он включает в себя выделение новой памяти и копирование элементов из оригинальных массивов в этот новый массив. Эти дополнительные накладные расходы обычно делают «concat» медленнее, чем `push '. Многие тесты показывают «push» на несколько порядков быстрее, чем «concat» во многих типичных сценариях, особенно там, где участвуют большие массивы или многие операции слияния.
Несмотря на это, кромки, когда «concat» может быть быстрее, включают:
1. Когда оригинальный массив не используется позже:
Если первоначальный массив больше не требуется, и предпочтительна неизменная операция, «concat» иногда может быть более эффективной при оптимизации высокого уровня, поскольку он позволяет избежать потенциальных накладных расходов от массива или внутренних перераспределения, которые могут произойти при повторных операциях push '. В таких случаях, особенно при оптимизации двигателей V8, создание свежего массива может извлечь выгоду из более предсказуемых паттернов памяти.
2. При использовании небольших массивов или нескольких элементов:
Для очень небольших массивов или когда количество добавляемых элементов минимально, разница в скорости между `push 'и` concat' может быть незначительной. Иногда, из -за внутренней оптимизации, «concat» может быть так же быстрым или немного быстрее, потому что накладные расходы вызова «применить» для «push» могут уравновесить стоимость копирования «concat».
3. Необываемые модели программирования:
В некоторых функциональных сценариях программирования или неизменной структуры данных «concat» предпочтительнее, потому что он не мутирует исходный массив. Несмотря на то, что это не является чистым усилением скорости, он может обеспечить лучшую оптимизацию двигателями JavaScript, которые способствуют неизменности, такие как структурное обмен или стратегии копирования на записи, особенно в библиотеках, разработанных вокруг этих парадигм. В этих контекстах, хотя и не типичном использовании JavaScript, специализированные реализации могут сделать конкатенацию быстрее, чем на основе мутаций.
4. Согласование нескольких массивов одновременно:
`concat 'может принимать несколько аргументов (массивов или элементов) и автоматически выполнять операцию с уплощением. При объединении многих массивов в одной операции «concat» может избежать нескольких вызовов, чтобы «push» и уменьшить накладные расходы в определенных двигателях JavaScript. Это может быть быстрее, чем последовательные вызовы `push`, где каждый вызов запускает накладные расходы, связанные с распространением аргумента или обновлениями внутренней длины массива.
5. Избегание накладных расходов на функцию с помощью `push.apply`:
Когда `push 'используется с` Apply' для распространения массива, он может запустить ограничения двигателя JavaScript на количество аргументов (различающихся в разных браузерах и версиях V8). Если размер массива превышает этот предел, `push.Apply` может выйти из строя или ухудшаться в производительности. `concat 'не имеет таких ограничений, что может сделать его быстрее или более надежным для чрезвычайно больших конкатенаций.
6. меньше распределения объектов в некоторых двигателях JavaScript для `concat`:
Некоторые двигатели JavaScript могут оптимизировать «concat» при конкретном использовании их внутренних стратегий управления памятью. Например, двигатели могут оптимизировать «concat», используя буферы копирования на записи или путем запуска буферов внутренних массивов, тем самым снижая стоимость копирования больших массивов при определенных условиях.
7. Используйте в специальных структурах данных или на типичных массивах:
При работе с типированными массивами или специальными объектами JavaScript, такими как неподвижные векторы (в некоторых библиотеках), методы конкатенации, смоделированные после «concat», могут быть разработаны для обеспечения логарифмической сложности слияния без полного копирования массивов. В таких случаях базовая конструкция структуры данных позволяет конкатенации превосходить простые операции «push», которые непосредственно изменяют структуры данных.
8. Сбор сбора мусора и соображения давления памяти:
В ситуациях с тяжелым давлением памяти или частыми изменениями, «push» может вызвать более частые перераспределения и копирование в базовом массивном буфере, запуская циклы сбора мусора. «Concat» производит новый массив один раз, потенциально позволяя получить более предсказуемые узоры сбора мусора, что может иногда повысить производительность в целом.
9. Код простота с большими конкатенациями:
Несмотря на то, что «concat» не напрямую связан с скоростью, синтаксически проще для объединения нескольких массивов или элементов без распространения и зацикля. Это может уменьшить случайные накладные расходы от кода пользователя, который может отрицать небольшие различия в производительности.
10. Различия в производительности по двигателям и версии JavaScript:
Различные двигатели JavaScript (V8 в Chrome, Spidermonkey в Firefox, JavaScriptCore в Safari) оптимизируют эти операции по -разному. Некоторые версии двигателя могут иметь необъяснимо оптимизированную «concat» для конкретных паттернов или размеров массива, таким образом, в тех временных случаях, демонстрирующих «concat», как быстрее в редких условиях.
11. Избегание побочных эффектов мутации:
Использование `concat` помогает избежать мутации, что в некоторых средах отладки или развития может уменьшить накладные расходы, вызванные изменениями мониторинга массива или запускаемые реактивные обновления в рамках. Это косвенное ускорение может сделать «concat» выгодным в конкретных сценариях уровня приложения.
12. Стратегии выравнивания памяти и распределения:
Двигатели иногда оптимизируют распределения памяти для массивов, созданных с помощью «concat», что приводит к оптимизированному копированию или обмену буфером, которые могут быть быстрее, чем повторяющиеся инкрементные операции `push ', которые несколько раз изменяют размер массивного буфера.
Таким образом, в то время как «push» обычно превосходит «concat» в типичных показателях производительности, существуют края. К ним относятся сценарии, требующие неизменности, огромные массивы, превышающие пределы аргументов, многопользовательские конкатенации, конкретные структуры данных и оптимизации JavaScript Engine. Каждый случай в значительной степени зависит от природы данных, внутренней реализации двигателя и контекста программирования. Понимание этих нюансов помогает разработчикам выбрать правильный метод, оптимизированный для их конкретных потребностей.
Общие советы по производительности предпочтение «push» для мутации массива и объединения, когда производительность является критической для многих случаев, но не является абсолютным. Для ясности кода, неизменности или конкретной оптимизации двигателя «concat» может быть быстрее или предпочтительнее в определенных условиях края. Эта тонкость является важной частью понимания операций массива JavaScript на продвинутом уровне.