Какая разница между массивами (2) и [undefined, undefined]?
[undefined, undefined, undefined].map(function(val, i) { return i });
возвращает [0, 1, 2], а
Array(3).map(function(val, i) { return i });
возвращает [undefined, undefined, undefined].
Почему?
Ответы
Ответ 1
В первом случае вы определили и инициализировали новый массив с тремя значениями undefined
, тогда как во втором случае у вас есть только определенный массив с возможная длина 3.
new Array(3)
- это то же самое, что и вы:
var arr = [];
arr.length = 3;
В результате, если свойство .length
неявно определено, метод .map()
может выполнять итерацию по массиву, выделенному в памяти, который в основном содержит нулевые определенные элементы (т.е. чисто пустые).
Ответ 2
Вы объявляете указатели на undefined объекты, записывающие undefined
. Таким образом, [undefined]
создает массив указателя на undefined. new Array(3)
создает массив указателей undefined, которые не зацикливаются на методах прототипа массива (включая .map
).
Справочник по MDN. Переменная undefined
фактически присваивает значение, даже если оно указывает на undefined
.
Ответ 3
Array(3)
просто берет пустой массив и вручную назначает ему длину:
> a = []
[]
> a.length = 3
3
> a
[ , , ]
Это не то же самое, что вручную создавать массив, содержащий элементы undefined:
> a = [undefined, undefined, undefined]
[ undefined, undefined, undefined ]
документация MDN для Array точно объясняет, что происходит:
Если единственным аргументом, переданным конструктору Array, является целое число от 0 до 2 32 -1 (включительно), новый пустой массив JavaScript и его длина будут установлены на это число. Если аргументом является любое другое число, генерируется исключение RangeError.
Итак, массив инициализируется пустым массивом []
. Это объясняет, почему map
не обрабатывает какие-либо элементы массива, потому что их нет.
Несколько примеров могут помочь. Когда массив инициализируется с помощью Array(3)
, он пуст, поэтому map
не имеет ничего для перебора:
> Array(3)
.map(function(val, i) { console.log(i); return i; });
[ , , ]
Сравните это со следующим примером, где вы можете увидеть, что каждое промежуточное значение массива выводится на консоль:
> [undefined, undefined, undefined]
.map(function(val, i) { console.log(i); return i; });
0
1
2
[ 0, 1, 2 ]
Ответ 4
Как упоминалось @VisioN, Array (3) определен, но неинициализирован. Интересно, что вы можете передать неинициализированный массив через Array.apply и инициализировать его. Я использовал это для заполнения массивов:
Array.apply(null, Array(3)).map(function(val,i) { return i; });
// [0, 1, 2]
Ответ 5
<script type="text/javascript">
test();
test2();
function test() {
[undefined, undefined, undefined].map(function(val, i) { console.log("un: " + val + "/" + i); return i; });
}
function test2() {
Array(3).map(function(val, i) { console.log("no: " + val + "/" + i); return i; });
}
</script>
Функция test() возвращает:
un: undefined/0
un: undefined/1
un: undefined/2
Функция test2() не возвращает значение;
- test() у вас есть объект, содержащий 3 значения (undefined)
- test2() имеет пустой массив длиной 3