[undefined, undefined, undefined].map(function(val, i) { return i });
возвращает [0, 1, 2], а
Array(3).map(function(val, i) { return i });
возвращает [undefined, 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].
Почему?
В первом случае вы определили и инициализировали новый массив с тремя значениями undefined
, тогда как во втором случае у вас есть только определенный массив с возможная длина 3.
new Array(3)
- это то же самое, что и вы:
var arr = [];
arr.length = 3;
В результате, если свойство .length
неявно определено, метод .map()
может выполнять итерацию по массиву, выделенному в памяти, который в основном содержит нулевые определенные элементы (т.е. чисто пустые).
Вы объявляете указатели на undefined объекты, записывающие undefined
. Таким образом, [undefined]
создает массив указателя на undefined. new Array(3)
создает массив указателей undefined, которые не зацикливаются на методах прототипа массива (включая .map
).
Справочник по MDN. Переменная undefined
фактически присваивает значение, даже если оно указывает на undefined
.
Array(3)
просто берет пустой массив и вручную назначает ему длину:
> a = []
[]
> a.length = 3
3
> a
[ , , ]
Это не то же самое, что вручную создавать массив, содержащий элементы undefined:
> a = [undefined, undefined, undefined]
[ undefined, undefined, undefined ]
Если единственным аргументом, переданным конструктору 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 ]
Как упоминалось @VisioN, Array (3) определен, но неинициализирован. Интересно, что вы можете передать неинициализированный массив через Array.apply и инициализировать его. Я использовал это для заполнения массивов:
Array.apply(null, Array(3)).map(function(val,i) { return i; });
// [0, 1, 2]
<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() не возвращает значение;