Я хотел бы проверить, является ли переменная массивом или отдельным значением в JavaScript.
Я нашел возможное решение ...
if (variable.constructor == Array)...
Это лучший способ сделать это?
Я хотел бы проверить, является ли переменная массивом или отдельным значением в JavaScript.
Я нашел возможное решение ...
if (variable.constructor == Array)...
Это лучший способ сделать это?
Есть несколько способов проверить, является ли переменная массивом или нет. Лучшее решение - это то, что вы выбрали.
variable.constructor === Array
Это самый быстрый способ в Chrome и, скорее всего, во всех других браузерах. Все массивы являются объектами, поэтому проверка свойства конструктора - быстрый процесс для движков JavaScript.
Если у вас возникают проблемы с выяснением того, является ли свойство объектов массивом, вы должны сначала проверить, существует ли это свойство.
variable.prop && variable.prop.constructor === Array
Некоторые другие способы:
Array.isArray(variable)
Обновление от 23 мая 2019 г. с использованием Chrome 75, спасибо @AnduAndrici за то, что он попросил меня вернуться к этому вопросу с его вопросом. Последний, на мой взгляд, самый уродливый и один из самых медленных самый быстрый. Он работает примерно на 1/5 скорости, как в первом примере. Этот парень примерно на 2-5% медленнее, но это довольно сложно сказать. Надежный в использовании! Вполне впечатлен результатом. Array.prototype, на самом деле является массивом. вы можете прочитать об этом здесь https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
variable instanceof Array
В первом примере этот метод работает примерно на 1/3 скорости. По-прежнему довольно солидный, выглядит чище, если вам нужен красивый код, а не производительность. Обратите внимание, что проверка чисел не работает, поскольку variable instanceof Number
всегда возвращает false
. Обновление: instanceof
теперь работает на 2/3 скорости!
Итак, еще одно обновление
Object.prototype.toString.call(variable) === '[object Array]';
Этот парень медленнее всех пытается проверить массив. Однако это универсальный магазин для любого типа, который вы ищете. Однако, поскольку вы ищете массив, просто используйте самый быстрый метод, описанный выше.
Кроме того, я провел несколько тестов: http://jsperf.com/instanceof-array-vs-array-isarray/35 Так что повеселитесь и проверьте это.
Примечание. @EscapeNetscape создал еще один тест, поскольку jsperf.com не работает. http://jsben.ch/#/QgYAV Я хотел убедиться, что исходная ссылка остается всегда, когда jsperf возвращается в онлайн.
variable && variable.constructor === Array
, чтобы убедиться, что переменная не пуста или не определена.
- person jemiloii; 12.01.2015
!!~variable.constructor.toString().indexOf('Array()')
, variable.constructor.toString() == Array().constructor.toString()
(вероятно, будут немного медленными) и Object.prototype.toString.call(variable) == '[object Array]'
- person Ismael Miguel; 26.03.2015
variable && variable.constructor
. Также следует отметить, что 5 instanceof Number
не работает должным образом. Экземпляр ищет прототип, числа не имеют прототипа, если вы его не указали. У чисел есть конструкторы.
- person jemiloii; 16.03.2016
instanceof
ими не пользуется. Что странно, потому что это единственная цель, согласно MDN ...
- person jemiloii; 16.03.2016
variable && variable.constructor === Array
- person jemiloii; 05.10.2016
Array.isArray(variable)
у меня даже не работал. Первый отлично справился!
- person awe; 20.09.2017
Array.isArray
- самый быстрый, а не самый медленный
- person Ferrybig; 25.09.2017
variable.constructor === Array
по-прежнему является принятым ответом как самый быстрый / самый эффективный? или variable instanceof Array
или Array.isArray(variable)
стали более жизнеспособными? - спрашивать, поскольку ответы / комментарии в некоторых местах довольно старые. Очень признателен :)
- person Andu Andrici; 21.05.2019
variable.constructor === Array
Если бы это было не так, я бы обновил его и указал причину, по которой я обновился.
- person jemiloii; 31.07.2019
instanceof
работает на 2/3 скорости исходного ответа. Значит ли это быстрее? Помедленнее? В формулировке есть некоторая двусмысленность, хотя, по общему признанию, контекст абзаца, кажется, показывает медленнее. Я провел несколько собственных тестов, изменив код в jsben.ch/QgYAV, но эти результаты показали, что instanceof
был самым быстрым . Кстати, jsben.ch/QgYAV теперь ссылается на пустой тест.
- person Sebastian Gaweda; 31.07.2019
Вы также можете использовать:
if (value instanceof Array) {
alert('value is Array!');
} else {
alert('Not an array');
}
Мне это кажется довольно изящным решением, но каждому свое.
Редактировать:
Начиная с ES5 теперь также:
Array.isArray(value);
Но это не работает в старых браузерах, если вы не используете полифиллы (в основном ... IE8 или аналогичные).
Array instanceof Object == true
.
- person Pierre; 29.11.2012
variable instanceof Object
, поскольку она не является экземпляром массива.
- person tuck; 01.05.2013
Array.prototype instanceof Array; // false
(должно быть верно); также ({ __proto__ : Array.prototype }) instanceof Array; // true
(должно быть ложным)
- person vortexwolf; 04.11.2013
Array.isArray(arr)
- person Dominic; 13.10.2014
Есть несколько решений со своими причудами. Эта страница дает хороший обзор . Одно из возможных решений:
function isArray(o) {
return Object.prototype.toString.call(o) === '[object Array]';
}
Я заметил, что кто-то упомянул jQuery, но я не знал, что существует функция isArray()
. Оказывается, он был добавлен в версии 1.3.
jQuery реализует это, как предлагает Питер:
isArray: function( obj ) {
return toString.call(obj) === "[object Array]";
},
Уже поверив jQuery (особенно их методам кроссбраузерной совместимости), я либо обновлюсь до версии 1.3 и воспользуюсь их функцией (при условии, что обновление не вызовет слишком много проблем), либо воспользуюсь этим предложенным методом непосредственно в моем код.
Большое спасибо за предложения.
В современных браузерах (и некоторых устаревших браузерах) вы можете делать
Array.isArray(obj)
(Поддерживается Chrome 5, Firefox 4.0, IE 9, Opera 10.5 и Safari 5)
Если вам нужна поддержка более старых версий IE, вы можете использовать es5-shim для полифил-массива .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
Примечание: ключевое слово 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)
prototype
? Кажется, должно быть Object.prototype.toString.call
.
- person Brock; 20.11.2014
Это старый вопрос, но, столкнувшись с той же проблемой, я нашел очень элегантное решение, которым хочу поделиться.
Добавление прототипа в массив делает его очень простым
Array.prototype.isArray = true;
Теперь, если у вас есть объект, который вы хотите протестировать, чтобы увидеть, является ли его массив, все, что вам нужно, это проверить новое свойство
var box = doSomething();
if (box.isArray) {
// do something
}
isArray доступен, только если это массив
Object.prototype.isArray = true;
! :(
- person ErikE; 30.09.2012
Array.isArray
- это метод (например, Array.isArray([1,2,3]) === true
), поэтому @ErikE не был троллем. Я бы не стал следовать этому ответу, поскольку он нарушит код в некоторых современных браузерах.
- person JaredMcAteer; 11.07.2013
{}.isArray === true
с моим решением, в этом весь смысл ...
- person ErikE; 12.07.2013
Array.prototype["com.my.unique.name"].isArray
;)
- person SOFe; 28.12.2018
Через Crockford:
function typeOf(value) {
var s = typeof value;
if (s === 'object') {
if (value) {
if (value instanceof Array) {
s = 'array';
}
} else {
s = 'null';
}
}
return s;
}
Основной недостаток, о котором упоминает Крокфорд, - это неспособность правильно определять массивы, которые были созданы в другом контексте, например window
. На этой странице есть гораздо более сложная версия, если этого недостаточно.
Если вы имеете дело только с EcmaScript 5 и выше, вы можете использовать встроенную функцию Array.isArray
e.g.,
Array.isArray([]) // true
Array.isArray("foo") // false
Array.isArray({}) // false
Мне лично нравится предложение Питера: 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 6-е издание, 7.10 говорится, что Array.isArray()
реализован с использованием Object.prototype.toString.call()
в ECMAScript 5. Также обратите внимание, что если вы собираетесь беспокоиться об изменении реализации toString()
, вам также следует беспокоиться об изменении любого другого встроенного метода. . Зачем использовать push()
? Кто-то может это изменить! Такой подход глупый. Вышеупомянутая проверка - это предлагаемое решение для тех, кто беспокоится о toString()
изменениях, но я считаю, что в этой проверке нет необходимости.
return Object.prototype.toString.call(o) === Object.prototype.toString.call([]);
- person Grant Lindsay; 24.06.2014
Когда я разместил этот вопрос, версия JQuery, которую я использовал, не включала функцию isArray
. Если бы это было так, я бы, вероятно, просто использовал его, полагая, что эта реализация является лучшим независимым от браузера способом выполнить эту конкретную проверку типа.
Поскольку JQuery теперь предлагает эту функцию, я бы всегда ее использовал ...
$.isArray(obj);
(начиная с версии 1.6.2) Он по-прежнему реализуется с использованием сравнений строк в форме
toString.call(obj) === "[object Array]"
Подумал, что добавлю еще один вариант для тех, кто, возможно, уже использует библиотеку Underscore.js в своем скрипте. Underscore.js имеет функцию isArray () (см. http://underscorejs.org/#isArray).
_.isArray(object)
Возвращает истину, если объект является массивом.
Array.isArray
, если он доступен, в противном случае - метод toString
.
- person Kris; 24.04.2014
Если вы используете Angular, вы можете использовать функцию angular.isArray ()
var myArray = [];
angular.isArray(myArray); // returns true
var myObj = {};
angular.isArray(myObj); //returns false
http://docs.angularjs.org/api/ng/function/angular.isArray
В JavaScript The Good Parts Крокфорда есть функция, проверяющая, является ли данный аргумент массивом:
var is_array = function (value) {
return value &&
typeof value === 'object' &&
typeof value.length === 'number' &&
typeof value.splice === 'function' &&
!(value.propertyIsEnumerable('length'));
};
Он объясняет:
Во-первых, мы спрашиваем, истинно ли значение. Мы делаем это, чтобы отклонить нулевые и другие ложные значения. Во-вторых, мы спрашиваем, является ли значение typeof «объектом». Это будет верно для объектов, массивов и (как ни странно) null. В-третьих, мы спрашиваем, имеет ли значение свойство длины, которое является числом. Это всегда будет верно для массивов, но обычно не для объектов. В-четвертых, мы спрашиваем, содержит ли значение метод сращивания. Это снова будет верно для всех массивов. Наконец, мы спрашиваем, является ли свойство length перечислимым (будет ли длина создаваться циклом for in?). Это будет неверно для всех массивов. Это самый надежный тест на массивность, который я нашел. Очень жаль, что это так сложно.
Универсальное решение представлено ниже:
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);};
concat
, и unshift
, этого недостаточно для проверки на unshift
?
- person Marco Demaio; 18.02.2014
concat
или unshift
, но менее вероятно, что они оба.
- person Kris; 24.04.2014
Я использовал эту строку кода:
if (variable.push) {
// variable is array, since AMAIK only arrays have push() method.
}
push
будет считаться массивом.
- person teleclimber; 28.04.2014
Для тех, кто кодирует гольф, ненадежный тест с наименьшим количеством символов:
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/
он работает аналогично текущему типу.
var user = [1,2,3]
typeOf(user); //[object Array]
Он думает, что может потребоваться небольшая тонкая настройка, и принимает во внимание вещи, которые я не встречал и не тестировал должным образом. так что дальнейшие улучшения приветствуются, будь то производительность или неправильный перенос typeOf.
Я думаю, что лучше всего использовать myObj.constructor == Object и myArray.constructor == Array. Это почти в 20 раз быстрее, чем при использовании toString (). Если вы расширяете объекты своими собственными конструкторами и хотите, чтобы эти творения также считались «объектами», это не сработает, но в остальном все будет быстрее. typeof работает так же быстро, как и метод конструктора, но typeof [] == 'object' возвращает true, что часто бывает нежелательно. http://jsperf.com/constructor-vs-tostring
Следует отметить, что null.constructor выдаст ошибку, поэтому, если вы можете проверять нулевые значения, вам сначала придется выполнить if (testThing! == null) {}
Поскольку свойство .length специально для массивов в javascript, вы можете просто сказать
obj.length === +obj.length // true if obj is an array
Underscorejs и несколько других библиотек используют этот короткий и простой трюк.
Я только что придумал:
if (item.length)
//This is an array
else
//not an array
if ('push' in variable.__proto__)
, самый быстрый и, возможно, лучший способ проверить, является ли некоторый var массивом. - person thednp   schedule 06.07.2015