Подтвердить что ты не робот

Каков наилучший способ узнать, является ли объект массивом

Насколько я знаю, существует три способа выяснить, является ли объект массивом

функцией isArray, если реализовано

Array.isArray()

toString

Object.prototype.toString.apply( obj ) === "[object Array]"

и instanceof

obj instanceof Array

Есть ли какая-то причина выбора одного над другим?

4b9b3361

Ответ 1

Лучшим способом, вероятно, будет использование стандартного Array.isArray(), если он будет реализован движком:

isArray = Array.isArray(myObject)

MDN рекомендует использовать метод toString(), когда Array.isArray не реализован:

Совместимость

Запуск следующего кода до создания любого другого кода Array.isArray, если он не доступен изначально. Это зависит от Object.prototype.toString не изменяется и вызывается для разрешения собственный метод Function.prototype.call.

if(!Array.isArray) {  
  Array.isArray = function (arg) {  
    return Object.prototype.toString.call(arg) == '[object Array]';  
  };  
}

Оба jQuery и underscore.js [source] используют способ toString() === "[object Array]".

Ответ 2

Если бы не было доказано, что у первого есть значительные преимущества в производительности, и моему приложению требуется каждая последняя унция скорости, я бы пошел за последним.

Причина - читаемость, чистая и простая.

Ответ 3

Если то, что вы пытаетесь сделать, - это решить, передан ли вам параметр - массив, который вы должны перебирать, там есть довольно много кода, который просто ищет атрибут .length и рассматривает как массив или псевдо-массив, если этот атрибут присутствует.

Это потому, что есть много вещей, которые на самом деле не являются массивами (но являются псевдо-массивами с возможностями типа массива), которые могут потребовать, чтобы ваш код обрабатывался как массив. Примерами некоторых из этих вещей являются объект jQuery или nodeList, возвращаемый из многих вызовов DOM. Вот пример кода:

// accepts:
//    single DOM element
//    array of DOM elements
//    nodeList as returned from various DOM functions like getElementsByClassName
//    any array like object with a .length attribute and items in numeric indexes from 0 to .length-1 like a jQuery object
function hideElements(input) {
    if (input.length !== undefined) {
        for (var i = 0, len = input.length; i < len; i++) {
            input[i].style.display = "none";
        }
    } else {
        input.style.display = "none";
    }
    return(input);
}

Функция jQuery .each() также просто проверяет переданный ей параметр .length(и проверяет, что это не функция), прежде чем принимать решение о том, что он должен перебираться как массив.

Если это не проблема, которую вы пытаетесь решить, я могу найти две ссылки на использование первой техники:

  • реализация jQuery isArray использует первый метод.
  • MDN (Mozilla Developer Network) рекомендует первый здесь.

Ответ 4

instanceof проверяет, находится ли данный конструктор (Array) в цепочке прототипов объекта, а ваш второй подход проверяет только фактический тип объекта. Другими словами, если ваш объект наследуется от Array, второй тест будет истинным, но первый будет false. Теперь, как правило, это не делается для наследования из массива (это не работает правильно в IE), но ходьба по прототипной цепочке предположительно добавляет некоторые накладные расходы (особенно если объект не является массивом).