Подтвердить что ты не робот

Использование новой декларации Array (n) JavaScript

Основной вопрос JavaScript: поскольку для массивов не существует жесткого ограничения, как в случае с Java (т.е. IndexOutOfBoundsException), что такое использование объявления, в котором мы указываем свойство length?

var a = new Array(10);

Я знаю, что он предопределяет длину и помещает "undefined" в эти пустые места. Достаточно ли этого для этого?

4b9b3361

Ответ 1

Есть много предполагаемых преимуществ объявления размера массива, но я думаю, что большинство воспринимаемых преимуществ - это просто FUD, которые передаются.

Лучшая производительность!/Это быстрее!

Насколько я могу судить, разница между предварительным распределением и динамическим распределением незначительна.

Более интересно, спецификация не утверждает, что массив должен быть установлен на заранее выделенную длину!

Из раздела 15.4.2.2 ECMA-262:

Если аргумент len является Number и ToUint32 (len) равен len, то свойство длина для вновь созданного объекта устанавливается в ToUint32 (len). Если аргумент len является Number и ToUint32 (len) не равен len, генерируется исключение RangeError.

Ненаучный сценарий для удовольствия: http://jsbin.com/izini

Это делает более понятным код!

Лично я не согласен.

Рассмотрим javascript, который вы написали в прошлом, и рассмотрите код, который, возможно, придется писать в будущем. Я не могу придумать ни одного случая, когда мне нужно было указать статический предел для одного из моих массивов. Я также утверждаю, что потенциальные проблемы с ограничением массивов в javascript сильно перевешивают выгоды, вызванные тем, что люди знают, о чем вы думали, без каких-либо фактических проверок. Позволяет взвешивать плюсы и минусы...

Плюсы:

  • Им будет легче понять, что именно вы должны делать.
  • Теперь они смогут найти ошибки, вызванные вашим предположением (язык на щеке)

Минусы:

  • Быстрые взгляды могут легко смутить "новый массив (10)" с "новым массивом (" 10 "), который делает совершенно разные вещи!
  • Вы вводите произвольный предел для кода без нормального ограничения длины, заставляя вас писать много кода котельной таблички, чтобы проверить и поддерживать лимит.
  • Вы накладываете произвольный лимит на код, который, возможно, был бы обобщен для работы с любой длиной значений.
  • Вы делаете предположение о том, как люди будут читать ваш код, предполагая, что альтернатива будет менее запутанной.

Вы также можете написать:

//I assume this array will always be length 10
var arr = new Array();

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

Хорошо, тогда.. почему вы думаете, что это даже там?

Удобство. Когда они писали спецификацию, я думаю, что они поняли две вещи.

  • Такое назначение будет заключаться в том, что разработчики, идущие с аналогичных языков, будут использоваться.
  • Реализации ECMAScript могут потенциально использовать его для повышения производительности.

Итак, они положили его туда. Спецификация определяет использование параметра, а не как его реализовать.

Ответ 2

Производительность на движке JavaScript V8.

Выполняя:

var arr = []; arr.length = 1000;

V8 предопределяет требуемую память для массива и поддерживает/устанавливает массив Hidden Class в компактный массив SMI (Small Int, 31 бит без знака). Однако это неверно, когда желаемая длина слишком велика, что приводит к тому, что HC устанавливается в разреженный массив (т.е. Карту).

Попробуйте использовать следующую ссылку в Chrome: http://jsperf.com/0-fill-n-size-array

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

Дополнительная информация: http://www.youtube.com/watch?v=UJPdhx5zTaw

Ответ 3

Clarity.

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

var xs = new Array(10);

В приведенном выше коде показано ваше намерение: иметь массив из 10 элементов.

var xs = [];

Приведенное выше ничего не дает; нет дополнительной информации.

Приветствия.

Ответ 4

Я не уверен, но я бы поспорил, что он распределяет память по-другому на низком уровне. Если вы знаете, что создаете 10 000 предметов, просто зарезервируйте это много места, а не динамически изменяя его в фоновом режиме все время.

Ответ 5

Я создал этот JSPerf, который демонстрирует проблему, включая ее различные версии. Аргументы, которые я нахожу, таковы:

  • Использование нового массива() может вести себя неожиданно, может быть переопределено
  • Параметр .length фактически не увеличивает размер массива в некоторых браузерах.
  • Удар по производительности на самом деле не там.

Я думаю, что эти тесты должны поместить эти аргументы в порядок, но следует отметить, что разные браузеры рассматривают эту проблему совсем по-другому. Похоже, Firefox оптимизирует и выясняет, насколько велик массив, а Chrome выделяет память, как и следовало ожидать. И, как обычно, Internet Explorer просто воняет этой задачей.

Ответ 6

Предположим, вы хотите, чтобы массив определенной длины был инициализирован определенным значением. Это не сработает:

scores = [].fill(0.0, 0, studentCount);

Он просто даст вам пустой массив, потому что fill() никогда не расширит массив за пределами его первоначальной длины.

Это будет работать:

scores = new Array(studentCount).fill(0.0, 0, studentCount);

Он даст вам массив значений studentCount, инициализированных до нуля.

Ответ 7

Не сложно сохранить размер массива. Взгляните на следующий пример:

function updateArray(){
    var a = [1,2,3,4,5,6,7,8,9,10]; //original array object
    var b = [11, 12, 13];  //New array object to be pushed
    a.splice(a.length-b.length, a.length);
    a.unshift.apply(a, b);
    return a;
}

a.unshift.apply(arg1, arg2) нажмите новый элемент сверху и a.push.apply(arg1, arg2) внизу.

Ответ 8

Целью предварительного выделения и использования new Array(n) помимо хорошей читабельности является предварительное резервирование стека памяти. Затем, когда мы начинаем использовать стек, мы избегаем всех проблем с перераспределением памяти и перераспределением и копированием элементов.

Не знаю о реализации двигателей и обработки для автоматического распределения. И насколько это оптимизировано. Но обычно они выделяют немного больше того, что инициализировали, тогда, когда мы достигаем конца, они перераспределяют с большим размером (следуя некоторой политике). И так далее. Так что использование push, unshift... и т.д. Может сильно повлиять на производительность.

Конечно, я не сказал, как мы можем оптимизировать и использовать new Array(n)?
Ответ прост. Он управляет стеком самостоятельно, как в обычных массивах в c или c++. Цель состоит в том, чтобы позволить двигателям активировать там реализованные механизмы оптимизации. Что в основном решит вопрос создания оптимизированного константного двоичного машинного кода (во многих случаях производительность в таких блоках будет эквивалентна или близка производительности кода, записанного в c/c++). Что является работой компилятора jit (как раз вовремя) и его комплекта оптимизации.

В нашем случае все это будет переводиться на использование нормальных массивов вместо динамических векторов. И проблема освобождения, перераспределения и копирования также будет устранена.

Чтобы лучше понять, я предлагаю эту золотую статью, которая рассматривает различные способы оптимизации массивов.

золотая статья.

И это видео, которое объясняет и демонстрирует, как v8 выполняет некоторую оптимизацию и насколько важны мелочи. https://www.youtube.com/watch?v=p-iiEDtpy6I

Бонусная нота

И, наконец, помните, что вам не нужно оптимизировать, пока это не имеет значения, и это имеет значение.

Если вы работаете в обычном приложении, без большой выгоды или важности, это не будет иметь значения (хороший пример - реактивные структуры, такие как реагирование, перераспределение существует всегда, (неизменяемые элементы), но это не имеет значения, и в В случае, если нам нужно оптимизировать по некоторым причинам, мы всегда можем это сделать, и мы можем применить вышеизложенное, например, с некоторыми крючками побочных эффектов (все такие рамки обеспечивают простоту и реактивность против бессмысленной оптимизации. С открытыми дверями для оптимизации, если это необходимо.).

И пример, и даже в таких средах, где вы можете подумать об оптимизации, - это когда у вас большой набор данных или обработка элементов, где подразумевается повторение и обработка. Примером может быть создание очень сложного модуля диаграммы. Вы можете работать с ним отдельно от платформы и оптимизировать все, что можете. А затем заверните это. Также мы можем упомянуть игры, комплексное лечение и вычисления... и т.д.

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

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

Ответ 9

Ну, лично я хочу очередь. Я хочу, чтобы очередь была длиной 10.

Самый простой способ сделать это - использовать метод массива push для размещения элементов в конце очереди и метод shift(), чтобы получить их от передней части массива.

Проблема в том, что если я хочу сделать простой метод "добавить" в свою очередь, и я напишу его так:

function addItemToArray(item, array){
    array.shift();
    array.push(item);
    return array;
}

тогда ничего хорошего не произойдет. Что лучше (на самом деле, что будет работать) заключается в объявлении моего массива следующим образом:

var maxSizeIsTen = new Array(10);

а затем использовать его повсюду. Также обратите внимание на "хороший" способ описания массива - никаких комментариев, которые никто не читает, и кто-либо, использующий этот код, будет в короткие сроки определять максимальный размер этого массива.

YAY!