Каков наилучший де-факто стандартный кроссбраузерный метод определения того, является ли переменная в JavaScript массивом или нет?
При поиске в Интернете можно найти множество различных предложений, некоторые из которых хороши, а некоторые нет.
Например, следующий базовый подход:
function isArray(obj) {
return (obj && obj.length);
}
Однако обратите внимание, что происходит, если массив пуст или obj на самом деле не массив, а реализует свойство длины и т. Д.
Итак, какая реализация является лучшей с точки зрения фактической работы, кроссбраузерности и эффективности?
javascript
arrays
stpe
источник
источник
Ответы:
Проверка типов объектов в JS осуществляется через
instanceof
, т.е.Это не сработает, если объект передается через границы кадра, поскольку каждый кадр имеет свой собственный
Array
объект. Вы можете обойти это, проверив внутреннее свойство [[Class]] объекта. Чтобы получить его, используйтеObject.prototype.toString()
(это гарантирует работу ECMA-262):Оба метода будут работать только для реальных массивов, а не для объектов, подобных массиву, таких как
arguments
списки объектов или узлов. Поскольку все объекты, подобные массиву, должны иметь числовоеlength
свойство, я бы проверил их следующим образом:Обратите внимание, что строки проходят эту проверку, что может привести к проблемам, поскольку IE не разрешает доступ к символам строки по индексу. Поэтому вы можете изменить
typeof obj !== 'undefined'
на,typeof obj === 'object'
чтобы исключить примитивы и объекты хоста с типами, отличными от'object'
. Это по-прежнему позволит передавать строковые объекты, которые придется исключать вручную.В большинстве случаев вы действительно хотите знать, можете ли вы перебирать объект с помощью числовых индексов. Поэтому было бы неплохо проверить, есть ли у объекта указанное свойство
0
, что можно сделать с помощью одной из следующих проверок:Приведение к объекту необходимо для правильной работы для примитивов, подобных массиву (то есть строк).
Вот код для надежных проверок массивов JS:
и повторяемые (т.е. непустые) объекты, подобные массиву:
источник
hasOwnProperty
метод, так просто префикс для вашихinstanceof
сobj.hasOwnProperty &&
; кроме того, это все еще проблема с IE7? мои простые тесты с помощью диспетчера задач показывают, что память была освобождена после сворачивания браузера ...Появление ECMAScript 5th Edition дает нам самый надежный метод проверки того, является ли переменная массивом, Array.isArray () :
Хотя принятый здесь ответ будет работать во фреймах и окнах для большинства браузеров, он не будет работать для Internet Explorer 7 и ниже , потому что
Object.prototype.toString
вызов массива из другого окна вернется[object Object]
, а не[object Array]
. IE 9, похоже, также регрессировал к этому поведению (см. Обновленное исправление ниже).Если вам нужно решение, которое работает во всех браузерах, вы можете использовать:
Он не совсем неразрушимый, но его может сломать только тот, кто изо всех сил пытается его сломать. Он помогает обойти проблемы IE7 и ниже и IE9. Ошибка все еще существует в IE 10 PP2 , но может быть исправлена до выпуска.
PS, если вы не уверены в решении, я рекомендую вам проверить его, сколько душе угодно, и / или прочитать сообщение в блоге. Есть и другие потенциальные решения, если вам неудобно использовать условную компиляцию.
источник
isArray
не возвращает true из массивов, созданных в других режимах документа? Мне придется разобраться с этим, когда у меня будет время, но я думаю, что лучше всего зарегистрировать ошибку в Connect, чтобы ее можно было исправить в IE 10.У Крокфорда есть два ответа на странице 106 книги «Хорошие стороны». Первый проверяет конструктор, но дает ложные отрицательные результаты в разных фреймах или окнах. Вот второй:
Крокфорд указывает, что эта версия идентифицирует
arguments
массив как массив, даже если в ней нет никаких методов массива.Его интересное обсуждение проблемы начинается на странице 105.
Существует одно интересное обсуждение (пост-Good Parts) здесь , который включает в себя это предложение:
Все обсуждения заставляют меня никогда не знать, является ли что-то массивом.
источник
jQuery реализует функцию isArray, которая предлагает лучший способ сделать это -
(фрагмент взят из jQuery v1.3.2 - немного скорректирован, чтобы иметь смысл вне контекста)
источник
Object.prototype.toString()
- вероятность того, что сломается, меньшеПохищение у гуру Джона Ресига и jquery:
источник
typeof
стандартизированы?Что вы собираетесь делать со значением, когда решите, что это массив?
Например, если вы намереваетесь перечислить содержащиеся значения, если он выглядит как массив ИЛИ, если это объект, используемый в качестве хеш-таблицы, то следующий код получает то, что вы хотите (этот код останавливается, когда функция закрытия возвращает что-либо другое чем "undefined". Обратите внимание, что он НЕ выполняет итерацию по контейнерам COM или перечислениям; это оставлено в качестве упражнения для читателя):
(Примечание: "o! = Null" тесты для null и undefined)
Примеры использования:
источник
for..in
- это плохо [tm])for..in
перебирает перечислимые свойства объектов; вы не должны использовать его с массивами, потому что: (1) он медленный; (2) сохранение порядка не гарантируется; (3) он будет включать любое определяемое пользователем свойство, установленное в объекте или любом из его прототипов, поскольку ES3 не включает никакого способа установки атрибута DontEnum; могут быть и другие проблемы, о которых я не думалЕсли вы делаете это в CouchDB (SpiderMonkey), используйте
Array.isArray(array)
как
array.constructor === Array
илиarray instanceof Array
не работают. Использованиеarray.toString() === "[object Array]"
действительно работает, но по сравнению с ним кажется довольно хитрым.источник
Если вам нужен кросс-браузер, вам нужен jQuery.isArray .
источник
В w3school есть пример, который должен быть вполне стандартным.
Чтобы проверить, является ли переменная массивом, они используют что-то похожее на это
протестировано в Chrome, Firefox, Safari, IE7
источник
constructor
для проверки типов слишком хрупко; используйте вместо этого одну из предложенных альтернативconstructor
обычное свойство DontEnum объекта-прототипа; это может не быть проблемой для встроенных типов, если никто не делает глупостей, но для пользовательских типов это легко может быть; мой совет: всегда используйтеinstanceof
, который проверяет цепочку прототипов и не полагается на свойства, которые могут быть произвольно перезаписаныОдну из наиболее изученных и обсуждаемых версий этой функции можно найти на сайте PHPJS . Вы можете ссылаться на пакеты или напрямую переходить к функции . Я настоятельно рекомендую этот сайт за хорошо продуманные эквиваленты функций PHP в JavaScript.
источник
Недостаточно ссылок, равных конструкторам. Иногда у них есть разные ссылки на конструктор. Поэтому я использую их строковые представления.
источник
{constructor:{toString:function(){ return "function Array() { [native code] }"; }}}
Заменить
Array.isArray(obj)
наobj.constructor==Array
образцы:
Array('44','55').constructor==Array
вернуть истину (IE8 / Chrome)'55'.constructor==Array
вернуть false (IE8 / Chrome)источник