Страницы

Поиск по вопросам

четверг, 13 февраля 2020 г.

Инициализация массива в JavaScript

#javascript


Привет.
Когда я создаю массив
var thingsv = new Array(length)

у меня нет возможности, проинициализировать его начальными значениями, потому что
формы вызова
var thingsv = new Array(length, value)

в языке нет (я не нашел). Приходится в цикле бежать по массиву и заполнять его. Нет
ли более удобного способа?
Спасибо.    


Ответы

Ответ 1



Например, так можно инициализировать массив из 10 элементов, каждый из который символ *: Array(10).join('*').split('')

Ответ 2



Предисловие Конструкции new Array(length, value) в JS нет, в связи с тем, как работает конструктор Array(). Если он принимает одно значение как аргумент, допустим, length, и typeof length == 'number' (приведение типов здесь работать не будет, даже .valueOf() у объекта не будет вызываться), тогда создастся пустой массив, заполненный чем-то непонятно, из length элементов. Можно даже заметить, что в разных браузерах в консоли это будет по-разному выглядеть, в общем так просто оставлять это не желательно. Но когда это условие не выполнено, то создаётся массив, элементами которого будет всё, что указано в аргументах конструктора. Кстати, запись Array() и new Array() ничем не отличается. И для инициализации пустого массива лучше (браузеру от этого приятнее) писать var mas = [], а не var mas = Array(). Акт первый К сожалению, нативное заполнение всего массива целиком появилось совсем недавно, с приходом ES6, и ещё плохо поддерживается браузерами, но как факт существует: Array(1000).fill(-1); Данная конструкция заполнит всю тысячу элементов массива значением -1. Плюс, как фишка, в функции можно задавать с какого по какое значение заполнить. Полное описание работы этой функции и её полифилл можно найти здесь. Акт второй Забавы ради можно предложить ещё один способ, появившийся в ES6. Будем использовать функцию Array.prototype.from(), она тоже не очень поддерживается браузерами, но немного лучше, чем Array.prototype.fill(): Array.from({length: 1000}, () => -1); Array.from({length: 1000}, function() { return -1; }); // аналогично Она принимает два объекта. Array-like объект (что-нибудь, что имеет свойство length), а вторым, функцию для вызова на каждый элемент нового массива (фактически будет выполнен неявный .map()). Подробное описание и полифилл можно посмотреть здесь. Акт третий С появлением ES5 заполнить массив стало возможно при помощи функции Array.prototype.map() вот так: Array.apply(null, {length: 1000}).map(function() {return -1}); Либо если пошутить и добавить щепотку ES6, то можно и вот так: Array.apply(null, {length: 1000}).map(() => -1); Думаю надо немного расжевать. Array.prototype.map() проигнорирует все пустые значения новоявленного массива (помните, я писал, что там что-то непонятное), поэтому надо сделать их явными. Делаем мы это так: Array.apply(null, {length: 1000}). В качестве контекста не имеет значения что передавать, а как аргумент вполне передадим array-like объект. Для итерирования по элементам необходимо только поле length, а так как элементов нет, то значениями всегда будет undefined. Метод рабочий, но лучше так не писать. Акт четвертый Можно сделать это по старинке, сначала выполнив Array.prototype.join(), соединив все элементы в строку, а затем Array.prototype.split(), разделив массив на атомарные сущности. Array(1000).join('-1').split(''); Плюс в том, что работает везде. Минус, в том, что заполнить массив можно только текстовыми значениями, как следствие необходимо выполнять приведение для получения чисел и всё-таки это медленно. Акт пятый, для справедливости Думаю надо написать и про самый проверенный и быстрый из ныне существующих методов заполнения массивов данными: var array = []; for (var i = 0; i < 1000; ++i) { array.push(-1); } Более быстрая и удобная его реализация: var array = Array(1000); for (var i = 0; i < array.length; array[i++] = -1); Заключение Выбирать способ заполнения массива данными (как и собственно всё остальное) всегда надо с умом, а я просто приведу небольшое сравнительное тестирование скорости выполнения всех операций на jsPerf. Осторожнее, на старых браузерах часть тестов работать не будет.

Комментариев нет:

Отправить комментарий