Как проверить, является ли переменная массивом в JavaScript? [дубликат]
этот вопрос уже есть ответ здесь:
- проверить, является ли объект массивом? 40 ответов
Я хотел бы проверить, является ли переменная массивом или одним значением в JavaScript.
Я нашел возможное решение...
if (variable.constructor == Array)...
Это лучший способ сделать это?
23 ответов
существует несколько способов проверить, является ли переменная массивом или нет. Лучшее решение-это то, которое вы выбрали.
variable.constructor === Array
это самый быстрый метод на Chrome, и, скорее всего, все другие браузеры. Все массивы являются объектами, поэтому проверка свойства конструктора является быстрым процессом для движков JavaScript.
если у вас возникли проблемы с выяснением, является ли свойство objects массивом, вы должны сначала проверить, является ли свойство там.
variable.prop && variable.prop.constructor === Array
некоторые другие способы:
variable instanceof Array
этот метод работает о 1/3 скорости в качестве первого примера. Все еще довольно твердый, выглядит чище, если вы все о красивом коде и не так много на производительности. Обратите внимание, что проверка номеров не работает как variable instanceof Number
всегда возвращает false
. обновление: instanceof
сейчас идет 2/3 скорости!
Array.isArray(variable)
этот последний, на мой взгляд, самый уродливый, и это один из самый медленный. Запуск около 1/5 скорости в качестве первого примера. Матрица.прототип, на самом деле массив. подробнее об этом можно прочитать здесь https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
Итак, еще одно обновление
Object.prototype.toString.call(variable) === '[object Array]';
этот парень самый медленный для проверки массива. Однако, это одна остановка магазин для любого типа, который вы ищете. Однако, поскольку вы ищете массив, просто используйте самый быстрый метод выше.
кроме того, я провел тест:http://jsperf.com/instanceof-array-vs-array-isarray/33 так что повеселись и проверь это.
Примечание: @EscapeNetscape создал еще один тест как jsperf.com вниз. http://jsben.ch/#/QgYAV я хотел убедиться, что оригинальная ссылка остается всякий раз, когда jsperf возвращается в интернет.
вы также можете использовать:
if (value instanceof Array) {
alert('value is Array!');
} else {
alert('Not an array');
}
Это кажется мне довольно элегантным решением, но каждому свое.
Edit:
по состоянию на ES5 теперь также:
Array.isArray(value);
но это сломается в старых браузерах, если вы не используете polyfills (в основном... IE8 или похожие).
Я заметил, что кто-то упомянул jQuery, но я не знал, что есть isArray()
есть несколько решений со всеми своими причудами. на этой странице дает хороший обзор. Одним из возможных решений является:
function isArray(o) {
return Object.prototype.toString.call(o) === '[object Array]';
}
в современных браузерах (и некоторых устаревших браузерах) вы можете сделать
Array.isArray(obj)
(при поддержке Chrome 5, Firefox 4.0, IE 9, Opera 10.5 и Safari 5)
Если вам нужно поддерживать более старые версии IE, вы можете использовать в ES5-shim и к массиву polyfill.isArray; или добавьте следующее
# only implement if no native implementation is available
if (typeof Array.isArray === 'undefined') {
Array.isArray = function(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
}
};
если вы используете jQuery, вы можете использовать jQuery.isArray(obj)
или $.isArray(obj)
. Если вы используете подчеркивание, вы можете использовать _.isArray(obj)
Если вам не надо обнаружение массивов, созданных в разных кадрах, вы также можете просто использовать instanceof
obj instanceof Array
Примечание: the arguments
ключевое слово, которое может быть использовано для доступа к аргументу функции, не является массивом, хотя он (обычно) ведет себя как один:
var func = function() {
console.log(arguments) // [1, 2, 3]
console.log(arguments.length) // 3
console.log(Array.isArray(arguments)) // false !!!
console.log(arguments.slice) // undefined (Array.prototype methods not available)
console.log([3,4,5].slice) // function slice() { [native code] }
}
func(1, 2, 3)
Это старый вопрос, но с той же проблемой я нашел очень элегантное решение, которым я хочу поделиться.
добавление прототипа в массив делает его очень простым
Array.prototype.isArray = true;
теперь если у вас есть объект, который вы хотите проверить, чтобы увидеть, если массив все, что вам нужно, чтобы проверить новое свойство
var box = doSomething();
if (box.isArray) {
// do something
}
isArray доступен, только если его массив
Via Крокфорд:
function typeOf(value) {
var s = typeof value;
if (s === 'object') {
if (value) {
if (value instanceof Array) {
s = 'array';
}
} else {
s = 'null';
}
}
return s;
}
основной недостаток Крокфорд упоминает неспособность правильно определить массивы, которые были созданы в другом контексте, например,window
.
Эта страница имеет гораздо более сложную версию, если этого недостаточно.
мне лично нравится предложение Петра:https://stackoverflow.com/a/767499/414784 (для ECMAScript 3. Для ECMAScript 5, Используйте Array.isArray()
)
комментарии к сообщению указывают, однако, что если toString()
изменяется вообще, этот способ проверки массива завершится ошибкой. Если вы действительно хотите быть конкретным и убедитесь, что toString()
не было изменено, и нет никаких проблем с атрибутом класса объектов ([object Array]
является атрибутом класса объекта, который является массивом), тогда я рекомендую сделать что-то вроде этого:
//see if toString returns proper class attributes of objects that are arrays
//returns -1 if it fails test
//returns true if it passes test and it's an array
//returns false if it passes test and it's not an array
function is_array(o)
{
// make sure an array has a class attribute of [object Array]
var check_class = Object.prototype.toString.call([]);
if(check_class === '[object Array]')
{
// test passed, now check
return Object.prototype.toString.call(o) === '[object Array]';
}
else
{
// may want to change return value to something more desirable
return -1;
}
}
обратите внимание, что в JavaScript The Definitive Guide 6th edition, 7.10, говорится Array.isArray()
реализуется с помощью Object.prototype.toString.call()
в ECMAScript 5. Также обратите внимание, что если вы собираетесь беспокоиться о toString()
реализация меняется, вы также должны беспокоиться о каждом другом встроенном изменении метода. Зачем использовать push()
? Кто-то может это изменить! Такой подход глуп. Вышеуказанная проверка является предлагаемым решением для тех, кто беспокоится о toString()
меняется, но я считаю, что чек не нужен.
думал, что я добавлю еще один вариант для тех, кто уже может использовать подчеркивание.библиотека js в их сценарии. Подчеркивать.js имеет функцию isArray () (см. http://underscorejs.org/#isArray).
_.isArray(object)
возвращает true, если объект является массивом.
Если вы имеете дело только с EcmaScript 5 и выше, вы можете использовать встроенный Array.isArray
функции
например,
Array.isArray([]) // true
Array.isArray("foo") // false
Array.isArray({}) // false
Если вы используете Angular, вы можете использовать angular.параметры isarray() функция
var myArray = [];
angular.isArray(myArray); // returns true
var myObj = {};
angular.isArray(myObj); //returns false
в Крокфорд это JavaScript Хорошие Части, есть функция для проверки, является ли данный аргумент массивом:
var is_array = function (value) {
return value &&
typeof value === 'object' &&
typeof value.length === 'number' &&
typeof value.splice === 'function' &&
!(value.propertyIsEnumerable('length'));
};
Он объясняет:
во-первых, мы спрашиваем, является ли значение истинным. Мы делаем это, чтобы отклонить null и другие ложные значения. Во-вторых, мы спрашиваем, является ли значение typeof "object". Это будет верно для объектов, массивов и (странно) null. В-третьих, мы спрашиваем, имеет ли значение свойство length, которое является числом. Это всегда будет верно для массивов, но обычно не для предметов. В-четвертых, мы спрашиваем, содержит ли значение метод splice. Это снова будет верно для всех массивов. Наконец, мы спрашиваем, является ли свойство length перечислимым (будет ли длина создаваться циклом for in?). Это будет false для всех массивов. Это самый надежный тест для arrayness, который я нашел. К сожалению, это так сложно.
я использовал эту строку кода:
if (variable.push) {
// variable is array, since AMAIK only arrays have push() method.
}
универсальное решение ниже:
Object.prototype.toString.call(obj)=='[object Array]'
начиная с ECMAScript 5, формальным решением является:
Array.isArray(arr)
кроме того, для старых библиотек JavaScript вы можете найти ниже решение, хотя оно недостаточно точно:
var is_array = function (value) {
return value &&
typeof value === 'object' &&
typeof value.length === 'number' &&
typeof value.splice === 'function' &&
!(value.propertyIsEnumerable('length'));
};
решения от http://www.pixelstech.net/topic/85-How-to-check-whether-an-object-is-an-array-or-not-in-JavaScript
код ссылка https://github.com/miksago/Evan.js/blob/master/src/evan.js
var isArray = Array.isArray || function(obj) {
return !!(obj && obj.concat && obj.unshift && !obj.callee);};
для тех, кто кода-гольф, ненадежный тест с наименьшим количеством символов:
function isArray(a) {
return a.map;
}
это обычно используется при обходе/уплощение иерархии:
function golf(a) {
return a.map?[].concat.apply([],a.map(golf)):a;
}
input: [1,2,[3,4,[5],6],[7,[8,[9]]]]
output: [1, 2, 3, 4, 5, 6, 7, 8, 9]
С w3schools:
function isArray(myArray) {
return myArray.constructor.toString().indexOf("Array") > -1;
}
мне понравился ответ Брайана:
function is_array(o){
// make sure an array has a class attribute of [object Array]
var check_class = Object.prototype.toString.call([]);
if(check_class === '[object Array]') {
// test passed, now check
return Object.prototype.toString.call(o) === '[object Array]';
} else{
// may want to change return value to something more desirable
return -1;
}
}
но вы могли бы просто сделать вот так:
return Object.prototype.toString.call(o) === Object.prototype.toString.call([]);
Я создал этот небольшой код, который может возвращать истинные типы.
Я еще не уверен в производительности, но это попытка правильно определить тип.
https://github.com/valtido/better-typeOf также немного написал об этом здесь http://www.jqui.net/jquery/better-typeof-than-the-javascript-native-typeof/
он работает, подобно текущему typeof.
var user = [1,2,3]
typeOf(user); //[object Array]
он думает, что ему может понадобиться немного тонкой настройки, и принять во внимание вещи, я не сталкивался или проверить его должным образом. поэтому дальнейшие улучшения приветствуются, будь то производительность или неправильный перенос typeOf.
Я думаю, используя myObj.конструктор= = объект и myArray.constructor= = Array-лучший способ. Его почти 20x быстрее, чем с помощью toString(). Если вы расширяете объекты своими собственными конструкторами и хотите, чтобы эти творения считались "объектами", это не работает, но в противном случае его путь быстрее. typeof так же быстро, как метод конструктора, но typeof []=='object' возвращает true, что часто будет нежелательным. http://jsperf.com/constructor-vs-tostring
следует отметить, что null.конструктор выдаст ошибку, поэтому, если вы можете проверять значения null, вам придется сначала сделать if (testThing!==null) {}
Так .свойство length для массива в JavaScript, вы можете просто сказать
obj.length === +obj.length // true if obj is an array
Underscorejs и несколько других библиотек используют этот короткий и простой трюк.