Зачем использовать JavaScript-массив? - PullRequest
18 голосов
/ 16 октября 2011

Firebug представляет (new Array(N)) как массив с N undefined s в нем. Недавно я столкнулся со сценарием, который продемонстрировал, что размерный массив со всеми значениями undefined отличается от вновь созданного размерного массива. Я хотел бы понять разницу.

Предположим, вы хотите создать список случайных целых чисел от 0 до 1000.

function kilorange() {
    return Math.floor(Math.random() * (1001));
}

no_random_numbers = (new Array(6)).map(kilorange);
my_random_numbers = [undefined, undefined, undefined,
                     undefined, undefined, undefined].map(kilorange);

Я бы ожидал, что no_random_numbers и my_random_numbers будут эквивалентны, но это не так. no_random_numbers - это еще один массив undefined с, тогда как my_random_numbers - это массив с шестью случайными целыми числами в нем. Кроме того, после добавления оператора console.count в kilorange я узнал, что моя функция никогда не вызывается для массива, созданного с помощью конструктора Array.

В чем разница, и почему map (и, вероятно, другие итерируемые методы) не обрабатывают вышеупомянутые массивы одинаково?

Ответы [ 6 ]

7 голосов
/ 16 октября 2011

Стандарт ES (15.4.4.19) определяет алгоритм для map, и из шага 8b совершенно ясно, что, поскольку ваш массив фактически не имеет ни одного из этих элементов, он вернет «пустой» массив длиной 6.

Как уже упоминалось, это связано с тем, что объекты массива в js (в отличие от их жестких аналогов в C) очень динамичны и потенциально разрежены (алгоритм проверки разреженности см. В 15.4).

2 голосов
/ 16 октября 2011

Посмотрите на этот пример и запустите его: http://jsfiddle.net/ArtPD/1/ (он создает два массива без использования над ними map и затем перечисляет ключ / значения каждого из них)

Я бы сказал, что (new Array(6)) не выделяет "именованные" свойства (поэтому он не создает "1": undefined, "2": undefined ...), в то время как другая форма [undefined, ... ] делает.

На самом деле, если я использую for (var i in ... ), два выхода:

no_random_numbers


my_random_numbers
0 undefined
1 undefined
2 undefined
3 undefined
4 undefined
5 undefined
2 голосов
/ 16 октября 2011

При использовании:

var a = new Array(N);

никакие значения не сохраняются в новом массиве, и даже индекс "свойства" не создаются. Вот почему map ничего не сделает с этим массивом.

Тот факт, что Firebug делает это, является ошибкой / особенностью Firebug. Вы должны помнить, что это консоль eval конверт. В консоли Firebug есть и другие ошибки / функции.

Например, в консоли Chrome приведенный выше массив a выглядит как [].

1 голос
/ 16 октября 2011

Хороший вопрос, хорошие ответы.Я немного поиграл с прототипом map из MDN .Если он адаптирован так, map будет работать для new Array([length])

Array.prototype.map = function(callback, thisArg) {
    var T, A, k;
    if (this == null) {
      throw new TypeError(" this is null or not defined");
    }
    var O = Object(this);
    var len = O.length >>> 0;
    if ({}.toString.call(callback) != "[object Function]") {
      throw new TypeError(callback + " is not a function");
    }
    if (thisArg) {
      T = thisArg;
    }
    A = new Array(len);
    k = 0;
    while(k < len) {
      var kValue, mappedValue;
      if (k in O || (O.length && !O[k])) {
//                  ^ added this
        kValue = O[ k ];
        mappedValue = callback.call(T, kValue, k, O);
        A[ k ] = mappedValue;
      }
      k++;
    }
    return A;
};

На основе ответа Casy Hopes вы также можете сделать расширение mapx, чтобы иметь возможность использовать map с некоторымиnew Array([length]):

Array.prototype.mapx = function(callback){
  return this.join(',').split(',').map(callback);
}
//usage
var no_random_numbers = new Array(6).mapx(kilorange);
0 голосов
/ 17 октября 2011

Чтобы ответить , почему вы бы запрограммировали массив, вы бы сделали это, чтобы вам не приходилось делать так много отдельных выделений. Выделение памяти занимает некоторое время и может запустить запуск сборки мусора, который может занять намного больше времени.

На типичной веб-странице вы не заметите разницу, но если вы делаете что-то серьезное, это может помочь.

0 голосов
/ 16 октября 2011

Чтобы ответить на заглавный вопрос (зачем использовать массивы), единственное использование, с которым я сталкивался при инициализации массива Array(n), - это создание строки n-1 длины:

var x = Array(6).join('-'); // "-----"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...