Большинство руководств, которые я читал по массивам в JavaScript (включая w3schools и devguru ), предполагают, что вы можете инициализировать массив определенной длины, передавая целое число в конструктор Array, используя var test = new Array(4);
синтаксис.
После широкого использования этого синтаксиса в моих файлах js я запустил один из файлов через jsLint , и он пришел в ужас :
Ошибка: проблема в строке 1, символ 22: ожидаемый «)», вместо этого «4».
var test = new Array (4);
Проблема в строке 1, символ 23: ожидается ';' и вместо этого увидел ')'.
var test = new Array (4);
Проблема в строке 1, символ 23: ожидал идентификатор и вместо этого увидел ')'.
После прочтения объяснения jsLint о его поведении , похоже, что jsLint не очень нравится new Array()
синтаксис, а вместо этого предпочитает []
при объявлении массивов.
Итак, у меня есть пара вопросов:
Во-первых, почему? Я рискую, используя new Array()
вместо этого синтаксис? Существуют ли несовместимости браузеров, о которых мне следует знать?
И во-вторых, если я переключусь на синтаксис в квадратных скобках, есть ли способ объявить массив и задать его длину в одной строке, или я должен сделать что-то вроде этого:
var test = [];
test.length = 4;
источник
new Array()
в целом, но это нормальнос указанием размера. Я думаю, что все сводится к согласованности кода во всем контексте.Ответы:
Почему вы хотите инициализировать длину? Теоретически в этом нет необходимости. Это может даже привести к сбивающему с толку поведению, потому что все тесты, которые используют,
length
чтобы выяснить, является ли массив пустым, сообщат, что массив не пуст.Некоторые тесты показывают, что установка начальной длины больших массивов может быть более эффективной, если массив заполняется впоследствии, но прирост производительности (если таковой имеется), кажется, отличается от браузера к браузеру.
jsLint не нравится,
new Array()
потому что конструктор неоднозначен.создает пустой массив длиной 4. Но
создает массив, содержащий значение
'4'
.Что касается вашего комментария: в JS вам не нужно инициализировать длину массива. Динамично растет. Вы можете просто сохранить длину в некоторой переменной, например
источник
for
цикл, который перебирает всю длину массива и заполняет его. Я предполагаю, что были бы другие способы сделать это в JavaScript, поэтому реальный ответ на вопрос «Почему я хочу это сделать?» «Из-за старых привычек, которые сформировались при программировании на других языках». :)new Array(10)
не создается массив с 10 неопределенными элементами. Он просто создает пустой массив длиной 10. Посмотрите этот ответ для противной правды: stackoverflow.com/questions/18947892/…Array(5)
дает вам массив с длиной 5, но без значений, поэтому вы не можете перебирать его.Array.apply(null, Array(5)).map(function () {})
дает вам массив длиной 5 и неопределенный как значения, теперь он может быть повторен.Array.apply(null, Array(5)).map(function (x, i) { return i; })
выдает массив длиной 5 и значениями 0,1,2,3,4.Array(5).forEach(alert)
ничего не делает,Array.apply(null, Array(5)).forEach(alert)
дает 5 предупрежденийES6
дает нам,Array.from
так что теперь вы также можете использоватьArray.from(Array(5)).forEach(alert)
Если вы хотите инициализировать с определенным значением, это хорошо знает ...
Array.from('abcde')
,Array.from('x'.repeat(5))
или
Array.from({length: 5}, (v, i) => i) // gives [0, 1, 2, 3, 4]
источник
Array
ему дается несколько аргументов, он перебираетarguments
объект и явно применяет каждое значение к новому массиву. Когда вы вызываетеArray.apply
с массивом или объектом со свойством length,Array
собираетесь использовать длину, чтобы явно установить каждое значение нового массива. Вот почемуArray(5)
дает массив из 5 значений, аArray.apply(null, Array(5))
массив из 5 неопределенных. Для получения дополнительной информации см. Этот ответ.Array.apply(null, Array(5))
Также можно записать в видеArray.apply(null, {length: 5})
. Разницы на самом деле не так много, но последнее однозначно ясно, что цель состоит в том, чтобы создать массивlength 5
, а не массив, содержащий5
С ES2015
.fill()
вы можете теперь просто сделать:Который намного лаконичнее, чем
Array.apply(0, new Array(n)).map(i => value)
Можно опускать
0
в.fill()
и запустить без аргументов, которые будут заполнять массив сundefined
. ( Тем не менее, это потерпит неудачу в Typescript )источник
When Array is called as a function rather than as a constructor, it also creates and initializes a new Array object. Thus the function call Array(…) is equivalent to the object creation expression new Array(…) with the same arguments
Array(n).fill()
ИЛИ
Примечание: вы не можете зациклить пустые слоты, т.е.
Array(4).forEach(() => …)
ИЛИ
( машинописный сейф )
ИЛИ
Классический метод с использованием функции (работает в любом браузере)
Создание вложенных массивов
При создании 2D массива
fill
следует интуитивно создавать новые экземпляры. Но то, что на самом деле произойдет, это тот же массив, который будет храниться в качестве ссылки.Решение
Таким образом, массив 3х2 будет выглядеть примерно так:
N-мерный массив
Инициализировать шахматную доску
источник
a[0].push(9);
// [ [6, 9], [6], [6] ]
должно бытьa[0].push(9);
// [ [6, 9], [6, 9], [6, 9] ]
потому, что каждый вложенный массив хранится как ссылка, поэтому изменение одного массива влияет на остальные. Вы, возможно, только что опечатали это, хотя я думаю :)Кратчайший:
источник
[
без использования,;
так как она будет пытаться разыменовать строку выше. Поэтому безопасным способом предсказуемо использовать эту строку в любой части кода будет:;[...Array(1000)]//.whateverOpsNeeded()
[...Array(5)].map((item, index) => ({ index }))
попробуйте и это:[...Array(5)]; console.log('hello');
const a = 'a'
и следующая строка[...Array(5)].//irrelevent
. Как вы думаете, к чему приведет первая строка? Это будет,const a = 'a'[...Array(5)]
что приведет к:Uncaught SyntaxError: Unexpected token ...
const a = 'a'
будет ошибка Lint в этом случае. Во всяком случае, это действительно не имеет ничего общего с этим ответом.ES6 представляет,
Array.from
который позволяет вам создаватьArray
из любых «подобных массиву» или итерируемых объектов:В этом случае
{length: 10}
представляет собой минимальное определение «подобного массиву» объекта: пустой объект с только определеннымlength
свойством.Array.from
позволяет использовать второй аргумент для отображения результирующего массива.источник
Это инициализирует свойство длины 4:
источник
var size = 42; var myArray = eval("["+",".repeat(size)+"]");
? (Не так серьезно;)Я удивлен, что не было предложено функционального решения, позволяющего установить длину в одну строку. Следующее основано на UnderscoreJS:
По причинам, указанным выше, я бы избегал этого, если бы я не хотел инициализировать массив определенным значением. Интересно отметить, что есть другие библиотеки, которые реализуют диапазон, включая Lo-dash и Lazy, которые могут иметь разные характеристики производительности.
источник
Пожалуйста, люди пока не отказываются от ваших старых привычек. Существует большая разница в скорости между выделением памяти один раз, затем работой с записями в этом массиве (как в старом), и распределением ее много раз по мере роста массива (что неизбежно происходит в системе с помощью других предлагаемых методов). ,
Конечно, все это не имеет значения, пока вы не захотите сделать что-нибудь классное с большими массивами. Тогда это так.
Поскольку в данный момент в JS все еще нет возможности установить начальную емкость массива, я использую следующее ...
Есть компромиссы:
standard
Массив имеет постоянно Оставляет столько пространства , как самый большой массив вы просили.Но если это согласуется с тем, что вы делаете, это может окупиться. Неофициальные сроки ставят
довольно быстро (около 50 мс для 10000, учитывая, что при n = 1000000 это заняло около 5 секунд), и
более чем за минуту (около 90 секунд для 10000 на той же хромированной консоли или примерно в 2000 раз медленнее). Это будет не только распределение, но и 10000 нажатий на цикл и т. Д.
источник
(это было вероятно лучше как комментарий, но получилось слишком долго)
Итак, после прочтения этого мне было любопытно, было ли предварительное распределение на самом деле быстрее, потому что в теории это должно быть. Тем не менее, этот блог дал несколько советов, советовавших против этого http://www.html5rocks.com/en/tutorials/speed/v8/ .
Так что все еще будучи неуверенным, я проверил это. И, как оказалось, на самом деле все идет медленнее.
Этот код выдает следующее после нескольких случайных запусков:
источник
источник
[5: 0]
это редкий массив и, вероятно, не то, что нужно.Вот еще одно решение
Первый аргумент
apply()
- это привязка объекта, о которой нам здесь наплевать, поэтому мы установили его наnull
.Array.apply(..)
вызываетArray(..)
функцию и распространяет{ length: 3 }
значение объекта в качестве аргументов.источник
new Array(n)
для инициализации массива, как этоnew Array(n).map(function(notUsed,index){...})
, но с этим подходом, как упомянул @zangw, вы можете сделать это. +1 от меня.Конструктор массива имеет неоднозначный синтаксис , и JSLint в конце концов только ранит ваши чувства.
Кроме того, ваш пример кода не работает, второй
var
оператор вызовет aSyntaxError
. Вы устанавливаете свойствоlength
массиваtest
, поэтому нет необходимости в другомvar
.Что касается ваших возможностей,
array.length
это единственный «чистый» вариант . Вопрос в том, зачем вам устанавливать размер в первую очередь? Попробуйте изменить код, чтобы избавиться от этой зависимости.источник
var test
. Это было неаккуратное копирование и вставка с моей стороны.Предполагая, что длина массива постоянна. В Javascript это то, что мы делаем:
const intialArray = new Array(specify the value);
источник
Как объяснено выше, использование
new Array(size)
несколько опасно. Вместо непосредственного использования поместите его в «функцию создания массива». Вы можете легко убедиться, что эта функция не содержит ошибок, и вы избежите опасностиnew Array(size)
прямого вызова . Кроме того, вы можете задать ему необязательное начальное значение по умолчанию. ЭтаcreateArray
функция делает именно это:источник
В большинстве ответов это рекомендуется для
fill
массива, потому что в противном случае «вы не можете итерировать по нему» , но это не так. Вы можете перебрать пустой массив, только не сforEach
. Циклы while, для циклов и для циклов i работают нормально.Не работает.
Эти работы:
Проверьте эту скрипку с приведенными выше примерами.
Также angulars
*ngFor
отлично работает с пустым массивом:источник
Вы можете установить длину массива, используя
array.length = youValue
Так было бы
источник
Причина, по которой вы не должны использовать
new Array
, демонстрируется этим кодом:Какой-то другой код может связываться с переменной Array. Я знаю, что это немного надумано, что кто-нибудь написал бы такой код, но все же ...
Кроме того, как сказал Феликс Кинг, интерфейс немного непоследователен и может привести к некоторым очень трудным для отслеживания ошибкам.
Если вам нужен массив с длиной = x, заполненный неопределенным (как это
new Array(x)
будет сделано), вы можете сделать это:источник
alert
иundefined
, потому что какой-то другой код может связываться с ними. Второй пример менее читабелен, чемnew Array(4)
и не дает того же результата: jsfiddle.net/73fKd