Как определить, является ли переменная массивом
каков наилучший де-факто стандартный кросс-браузерный метод для определения того, является ли переменная в JavaScript массивом или нет?
поиск в интернете есть ряд различных предложений, некоторые хорошие и довольно много недействительных.
например, следующий базовый подход:
function isArray(obj) {
return (obj && obj.length);
}
однако обратите внимание, что происходит, если массив пуст, или obj на самом деле не является массивом, но реализует свойство length и т. д.
Так что реализация является ли лучшим с точки зрения реальной работы, будучи кросс-браузером и по-прежнему эффективно работать?
12 ответов:
проверка типов объектов в JS выполняется через
instanceof, т. е.obj instanceof Arrayэто не будет работать, если объект передается через границы кадра, а каждый кадр имеет свою собственную
прибытие ECMAScript 5th Edition дает нам самый надежный метод тестирования, если переменная является массивом,массив.isArray ():
Array.isArray([]); // trueв то время как принятый ответ здесь будет работать через рамы и окна для большинства браузеров, это не для Internet Explorer 7 и ниже, потому что
Object.prototype.toStringвызов массива из другого окна вернет[object Object], а не[object Array]. IE 9, похоже, также регрессировал к этому поведению (см. обновленное исправление ниже).Я не буду вдаваться во все мелкие детали решения здесь, Если вы заинтересованы в том, что вы можете прочитать этот блог. Однако, если вы хотите решение, которое работает во всех браузерах, вы можете использовать:
(function () { var toString = Object.prototype.toString, strArray = Array.toString(), jscript = /*@cc_on @_jscript_version @*/ +0; // jscript will be 0 for browsers other than IE if (!jscript) { Array.isArray = Array.isArray || function (obj) { return toString.call(obj) == "[object Array]"; } } else { Array.isArray = function (obj) { return "constructor" in obj && String(obj.constructor) == strArray; } } })();Он не совсем нерушим, но он будет сломан только тем, кто изо всех сил пытается его сломать. Он работает вокруг проблем в IE7 и ниже и IE9. ошибка все еще существует в IE 10 PP2, но это может быть исправлено до релиза.
PS, Если вы не уверены в решении, то я рекомендую вам проверить его на содержание вашего сердца и/или прочитать сообщение в блоге. Есть и другие потенциальные решения, если вам неудобно использовать условную компиляцию.
Крокфорд имеет два ответа на странице 106 "хорошие части."Первый проверяет конструктор, но даст ложные негативы в разных кадрах или окнах. Вот второй:
if (my_value && typeof my_value === 'object' && typeof my_value.length === 'number' && !(my_value.propertyIsEnumerable('length')) { // my_value is truly an array! }Крокфорд указывает, что эта версия будет идентифицировать
argumentsмассив как массив, даже если он не имеет ни одного из методов массива.есть еще интересная дискуссия (пост-хорошие части)здесь который включает в себя это предложение:
var isArray = function (o) { return (o instanceof Array) || (Object.prototype.toString.apply(o) === '[object Array]'); };все обсуждение заставляет меня никогда не хотеть знать, является ли что-то массивом.
jQuery реализует функцию isArray, которая предлагает лучший способ сделать это
function isArray( obj ) { return toString.call(obj) === "[object Array]"; }(фрагмент взят из jQuery v1.3. 2 - слегка скорректирован, чтобы иметь смысл вне контекста)
кража у гуру Джона отставки и jquery:
function isArray(array) { if ( toString.call(array) === "[object Array]") { return true; } else if ( typeof array.length === "number" ) { return true; } return false; }
что вы собираетесь делать со значением, как только вы решите, что это массив?
например, если вы собираетесь перечислить содержащиеся значения, если это выглядит как массив или если это объект, используемый в качестве хэш-таблицы, то следующий код получает то, что вы хотите (этот код останавливается, когда функция закрытия возвращает что-либо, кроме "undefined". Обратите внимание, что он не выполняет итерацию по COM-контейнерам или перечислениям; это остается в качестве упражнения для читатель):
function iteratei( o, closure ) { if( o != null && o.hasOwnProperty ) { for( var ix in seq ) { var ret = closure.call( this, ix, o[ix] ); if( undefined !== ret ) return ret; } } return undefined; }(Примечание: "o != null " тесты для обоих null & undefined)
пример использования:
// Find first element who's value equals "what" in an array var b = iteratei( ["who", "what", "when" "where"], function( ix, v ) { return v == "what" ? true : undefined; }); // Iterate over only this objects' properties, not the prototypes' function iterateiOwnProperties( o, closure ) { return iteratei( o, function(ix,v) { if( o.hasOwnProperty(ix) ) { return closure.call( this, ix, o[ix] ); } }) }
Если вы хотите кросс-браузер, вы хотите jQuery.isArray.
On w3school есть пример, который должен быть вполне стандартным.
чтобы проверить, является ли переменная массивом, они используют что-то похожее на это
function arrayCheck(obj) { return obj && (obj.constructor==Array); }протестировано на Chrome, Firefox, Safari, ie7
если вы делаете это в CouchDB (SpiderMonkey), то используйте
Array.isArray(array)как
array.constructor === Arrayилиarray instanceof Arrayне работают. Используяarray.toString() === "[object Array]"работает, но, кажется, довольно сомнительный в сравнении.
один из лучших исследованных и обсуждаемых вариантов этой функции можно найти на сайт PHPJS. Вы можете ссылаться на пакеты, или вы можете перейти к напрямую. Я настоятельно рекомендую сайт для хорошо построенных эквивалентов функций PHP в JavaScript.
недостаточно ссылок, равных конструкторам. Иногда они имеют разные ссылки конструктора. Поэтому я использую их строковые представления.
function isArray(o) { return o.constructor.toString() === [].constructor.toString(); }
заменить
Array.isArray(obj)byobj.constructor==Arrayпримеры :
Array('44','55').constructor==Arrayreturn true (IE8 / Chrome)
'55'.constructor==Arrayreturn false (IE8 / Chrome)
Comments