JavaScript "new Array (n)" и "Array.prototype.map" странность - PullRequest
179 голосов
/ 31 марта 2011

Я наблюдал это в Firefox-3.5.7 / Firebug-1.5.3 и Firefox-3.6.16 / Firebug-1.6.2

Когда я запускаю Firebug:

    >>> x = new Array(3)
    [undefined, undefined, undefined]
    >>> y = [undefined, undefined, undefined]
    [undefined, undefined, undefined]

    >>> x.constructor == y.constructor
    true

    >>> x.map(function(){ return 0; })
    [undefined, undefined, undefined]
    >>> y.map(function(){ return 0; })
    [0, 0, 0]

Что здесь происходит? Это ошибка, или я неправильно понимаю, как использовать new Array(3)?

Ответы [ 13 ]

3 голосов
/ 31 марта 2011

Не ошибка.Вот как конструктор Array определен для работы.

Из MDC:

Когда вы задаете один числовой параметр с помощью конструктора Array, вы указываете начальную длину массива.Следующий код создает массив из пяти элементов:

var billingMethod = new Array(5);

Поведение конструктора Array зависит от того, является ли один параметр числом.

Метод .map() включает в итерацию только те элементы массива, которым явно присвоены значения.Даже явное присвоение undefined приведет к тому, что значение будет считаться подходящим для включения в итерацию.Это кажется странным, но по сути это разница между явным свойством undefined объекта и отсутствующим свойством:

var x = { }, y = { z: undefined };
if (x.z === y.z) // true

У объекта x нет свойства с именем "z", иобъект y делает.Однако в обоих случаях представляется, что «значение» свойства равно undefined.В массиве ситуация аналогична: значение length неявно выполняет присвоение значения всем элементам от нуля до length - 1.Поэтому функция .map() ничего не будет делать (не будет вызывать обратный вызов) при вызове массива, вновь созданного с помощью конструктора Array и числового аргумента.

0 голосов
/ 10 октября 2018

Вот простой вспомогательный метод в качестве обходного пути:

Простая карта для

function mapFor(toExclusive, callback) {
    callback = callback || function(){};
    var arr = [];
    for (var i = 0; i < toExclusive; i++) {
        arr.push(callback(i));
    }
    return arr;
};

var arr = mapFor(3, function(i){ return i; });
console.log(arr); // [0, 1, 2]
arr = mapFor(3);
console.log(arr); // [undefined, undefined, undefined]

Полный пример

Вот более полный пример (с проверкой работоспособности), который также позволяет указать необязательный начальный индекс:

function mapFor() {
var from, toExclusive, callback;
if (arguments.length == 3) {
    from = arguments[0];
    toExclusive = arguments[1];
    callback = arguments[2];
} else if (arguments.length == 2) {
    if (typeof arguments[1] === 'function') {
        from = 0;
        toExclusive = arguments[0];
        callback = arguments[1];
    } else {
        from = arguments[0];
        toExclusive = arguments[1];
    }
} else if (arguments.length == 1) {
    from = 0;
    toExclusive = arguments[0];
}

callback = callback || function () {};

var arr = [];
for (; from < toExclusive; from++) {
    arr.push(callback(from));
}
return arr;
}

var arr = mapFor(1, 3, function (i) { return i; });
console.log(arr); // [1, 2]
arr = mapFor(1, 3);
console.log(arr); // [undefined, undefined]
arr = mapFor(3);
console.log(arr); // [undefined, undefined, undefined]

Обратный отсчет

Управление индексом, переданным обратному вызову, позволяет считать в обратном направлении:

var count = 3;
var arr = arrayUtil.mapFor(count, function (i) {
    return count - 1 - i;
});
// arr = [2, 1, 0]
0 голосов
/ 31 марта 2011

В Chrome, если я наберу new Array(3), я получу [], поэтому я предполагаю, что вы столкнулись с ошибкой браузера.

...