Я наблюдал это в Firefox-3.5.7 / Firebug-1.5.3 и Firefox-3.6.16 / Firebug-1.6.2
Когда я запускаю Firebug:
var x = new Array(3)
console.log(x)
// [undefined, undefined, undefined]
var y = [undefined, undefined, undefined]
console.log(y)
// [undefined, undefined, undefined]
console.log( x.constructor == y.constructor) // true
console.log(
x.map(function() { return 0; })
)
// [undefined, undefined, undefined]
console.log(
y.map(function() { return 0; })
)
// [0, 0, 0]
Что тут происходит? Это ошибка, или я неправильно понимаю, как использовать new Array(3)
?
javascript
arrays
map-function
колокольчик-рапунцель
источник
источник
var y = x.map(function(){return 0; });
, и я получаю это как для нового метода Array (), так и для литерала массива. Я тестировал в Firefox 4 и Chrome.Ответы:
Похоже, что первый пример
Создает массив с неопределенными указателями.
А вторая создает массив с указателями на 3 неопределенных объекта, в этом случае сами указатели НЕ являются неопределенными, только те объекты, на которые они указывают.
Поскольку карта запускается в контексте объектов в массиве, я считаю, что первая карта вообще не запускает функцию, а вторая удается запустить.
источник
map
вызывает предоставленную функцию обратного вызова один раз для каждого элемента в массиве, по порядку и создает новый массив из результатов.callback
Вызывается только для индексов массива, которые имеют присвоенные значения ; она не вызывается для индексов, которые были удалены или которым никогда не присваивались значения. " В этом случаеx
значения не имеют явно назначенных значений, тогда как значенияy
были назначены, даже если это было значениеundefined
.(new Array(1))[0] === [undefined][0]
.hasOwnProperty
если только у васhasOwnProperty
нет ошибки:(new Array(1)).hasOwnProperty(0) === false
и[undefined].hasOwnProperty(0) === true
. На самом деле, вы можете сделать то же самое сin
:0 in [undefined] === true
и0 in new Array(0) === false
.x = new Array(3);
эквивалентноx = [,,,];
, нетx = [undefined, undefined, undefined]
.У меня была задача, что я знал только длину массива и нуждался в преобразовании элементов. Я хотел сделать что-то вроде этого:
Чтобы быстро создать массив следующим образом:
Но это не сработало, потому что: (см. Ответ Джонатана Лоновски несколькими ответами выше)
Решением может быть заполнение элементов массива любым значением (даже неопределенным) с помощью Array.prototype.fill ()
Показать фрагмент кода
Обновить
Другое решение может быть:
источник
undefined
в.fill()
методе, слегка упрощая код доlet arr = new Array(10).fill().map((val,idx) => idx);
Array.from(Array(10))
С ES6 вы можете сделать это
[...Array(10)].map((a, b) => a)
быстро и просто!источник
new Array(10).fill()
. Тот же результат, что и[...Array(10)]
[...Array(10).keys()]
Решение ES6:
Не работает на машинописи (2.3), хотя
источник
Array(10).fill("").map( ...
это то, что работало для меня с Typescript 2.9Массивы разные. Разница в том, что
new Array(3)
создается массив длиной три, но без свойств, а[undefined, undefined, undefined]
массив длиной три и три свойства с именами «0», «1» и «2», каждое со значениемundefined
. Вы можете увидеть разницу, используяin
оператор:Это связано с немного запутанным фактом, что если вы пытаетесь получить значение несуществующего свойства любого собственного объекта в JavaScript, он возвращает
undefined
(а не выдает ошибку, как это происходит, когда вы пытаетесь сослаться на несуществующую переменную ), что совпадает с тем, что вы получаете, если ранее для свойства было явно установлено значениеundefined
.источник
Со страницы MDC для
map
:[undefined]
фактически применяет установщик к индексу (-ам), так что онmap
будет повторяться, тогда какnew Array(1)
просто инициализирует индекс (-ы) значением по умолчанию,undefined
поэтомуmap
он пропускается.Я считаю, что это одинаково для всех итерационных методов .
источник
В спецификации ECMAScript 6-е издание.
new Array(3)
только определить свойствоlength
и не определять свойства индекса, как{length: 3}
. см. https://www.ecma-international.org/ecma-262/6.0/index.html#sec-array-len Шаг 9.[undefined, undefined, undefined]
будет определять свойства индекса и свойства длины, как{0: undefined, 1: undefined, 2: undefined, length: 3}
. см. https://www.ecma-international.org/ecma-262/6.0/index.html#sec-runtime-semantics-arrayaccumulationElementList
Шаг 5.методы
map
,every
,some
,forEach
,slice
,reduce
,reduceRight
,filter
из массива будет проверять свойство индекса поHasProperty
внутреннему методу, поэтомуnew Array(3).map(v => 1)
не будет ссылаться на обратном вызов.для получения более подробной информации см. https://www.ecma-international.org/ecma-262/6.0/index.html#sec-array.prototype.map.
Как исправить?
источник
Я думаю, что лучший способ объяснить это - посмотреть, как Chrome справляется с этим.
Так что на самом деле происходит то, что new Array () возвращает пустой массив, имеющий длину 3, но без значений. Поэтому, когда вы работаете
x.map
с технически пустым массивом, нечего настраивать.Firefox просто «заполняет» эти пустые слоты,
undefined
даже если у него нет значений.Я не думаю, что это явно ошибка, просто плохой способ представить, что происходит. Я полагаю, что Chrome "более правильный", потому что он показывает, что в массиве на самом деле ничего нет.
источник
Просто столкнулся с этим. Конечно, было бы удобно иметь возможность использовать
Array(n).map
.Array(3)
дает примерно{length: 3}
[undefined, undefined, undefined]
создает пронумерованные свойства:{0: undefined, 1: undefined, 2: undefined, length: 3}
.Реализация map () действует только на определенные свойства.
источник
Не ошибка Вот как конструктор Array определен для работы.
От MDC:
.map()
Метод включает в себя только в итерационных элементах массива , которые явно имели значение , присвоенное. Даже явное присвоениеundefined
приведет к тому, что значение будет считаться подходящим для включения в итерацию. Это кажется странным, но по сути это разница между явнымundefined
свойством объекта и отсутствующим свойством:У объекта
x
нет свойства с именем "z", и у объектаy
есть. Однако в обоих случаях представляется, что «ценность» этого свойства равнаundefined
. В массиве ситуация аналогична: значениеlength
неявно выполняет присваивание значения всем элементам от нуля до концаlength - 1
. Поэтому.map()
функция не будет ничего делать (не будет вызывать обратный вызов) при вызове массива, вновь созданного с помощью конструктора Array и числового аргумента.источник
undefined
навсегда?x = []
вместоx = new Array()
Если вы делаете это для того, чтобы легко заполнить массив значениями, не можете использовать заливку по соображениям поддержки браузера и действительно не хотите делать цикл for, вы также можете сделать,
x = new Array(3).join(".").split(".").map(...
что даст вам массив пустых строки.Я должен сказать, что это ужасно, но, по крайней мере, проблема и намерение достаточно четко изложены.
источник
Поскольку вопрос в том, почему, это связано с тем, как был разработан JS.
Есть две основные причины, по которым я могу объяснить это поведение:
Производительность: дано,
x = 10000
иnew Array(x)
для конструктора имеет смысл избегать циклического изменения от 0 до 10000 для заполнения массиваundefined
значениями.Неявно "undefined": Give
a = [undefined, undefined]
иb = new Array(2)
,a[1]
иb[1]
оба будут возвращатьсяundefined
, ноa[8]
иb[8]
также будут возвращаться,undefined
даже если они находятся вне диапазона.В конечном счете, обозначение
empty x 3
является ярлыком, позволяющим избежать установки и отображения длинного спискаundefined
значений, которые вundefined
любом случае существуют, поскольку они не объявлены явно.Примечание: данный массив
a = [0]
иa[9] = 9
,console.log(a)
вернется(10) [0, empty x 8, 9]
, автоматически заполняя пробел, возвращая разницу между двумя значениями, объявленными явно.источник
По причинам, подробно изложенным в других ответах,
Array(n).map
не работает. Тем не менее, в ES2015Array.from
принимает функцию карты:источник
Вот простой метод утилиты в качестве обходного пути:
Простая карта для
Полный пример
Вот более полный пример (с проверками работоспособности), который также позволяет указать необязательный начальный индекс:
Отсчет
Управление индексом, переданным обратному вызову, позволяет считать в обратном направлении:
источник