Использование новой декларации Array (n) JavaScript
Основной вопрос JavaScript: поскольку для массивов не существует жесткого ограничения, как в случае с Java (т.е. IndexOutOfBoundsException), что такое использование объявления, в котором мы указываем свойство length?
var a = new Array(10);
Я знаю, что он предопределяет длину и помещает "undefined" в эти пустые места. Достаточно ли этого для этого?
Ответы
Ответ 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!