Я хотел бы проверить, является ли переменная либо массивом, либо единственным значением в 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, выкрикивайте @Andu Andrici за то, что я снова вернулась к нему со своим вопросом. Последний, на мой взгляд, самый уродливый и один из самых медленных из самых быстрых. Запуск около 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 возвращается в онлайн.
Вы также можете использовать:
if (value instanceof Array) {
alert('value is Array!');
} else {
alert('Not an array');
}
Мне кажется, это довольно элегантное решение, но для каждого из них.
Изменить:
В ES5 теперь также есть:
Array.isArray(value);
Но это сломается на старых браузерах, если вы не используете полисы (в основном... IE8 или аналогичные).
Я заметил, что кто-то упомянул jQuery, но я не знал, что существует функция isArray()
. Оказывается, он был добавлен в версию 1.3.
jQuery реализует его, как предлагает Питер:
isArray: function( obj ) {
return toString.call(obj) === "[object Array]";
},
Положив много веры в jQuery (особенно их методы совместимости с несколькими браузерами), я либо обновляюсь до версии 1.3, либо воспользуюсь их функцией (при условии, что обновление не вызовет слишком много проблем) или используйте этот предложенный метод непосредственно в мой код.
Большое спасибо за предложения.
Существует множество решений со всеми их собственными причудами. Эта страница дает хороший обзор. Одно из возможных решений:
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-подкладку к polyfill Array.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)
Это старый вопрос, но с той же проблемой я нашел очень элегантное решение, которое хочу поделиться.
Добавление прототипа в массив делает его очень простым
Array.prototype.isArray = true;
Теперь, если у вас есть объект, который вы хотите протестировать, чтобы проверить, нужен ли ему массив, который вам нужен, чтобы проверить новое свойство
var box = doSomething();
if (box.isArray) {
// do something
}
isArray доступен только в том случае, если его массив
Через 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
.
Эта страница имеет гораздо более сложную версию, если этого недостаточно.
Мне лично нравится предложение Питера: fooobar.com/questions/990/... (для 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 an array
//returns false if it passes test and it 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. Окончательное руководство. 6-е издание, 7.10, говорит, что Array.isArray()
реализуется с использованием Object.prototype.toString.call()
в ECMAScript 5. Также обратите внимание, что если вы собираетесь беспокоиться о смене реализации toString()
, вам также следует беспокойство о каждом другом встроенном методе тоже. Зачем использовать push()
? Кто-то может это изменить! Такой подход глуп. Вышеупомянутая проверка является предлагаемым решением для тех, кто обеспокоен изменением toString()
, но я считаю, что проверка не нужна.
Когда я разместил этот вопрос, версия JQuery, которую я использовал, не включала функцию isArray
. Если бы у меня было это, я бы, вероятно, просто использовал его, полагая, что реализация будет лучшим браузером, независимым способом выполнения этой конкретной проверки типа.
Так как JQuery теперь предлагает эту функцию, я всегда буду использовать ее...
$.isArray(obj);
(начиная с версии 1.6.2) Он по-прежнему реализуется с использованием сравнений строк в форме
toString.call(obj) === "[object Array]"
Если вы имеете дело только с EcmaScript 5 и выше, тогда вы можете использовать встроенную функцию Array.isArray
например,
Array.isArray([]) // true
Array.isArray("foo") // false
Array.isArray({}) // false
Думаю, я добавлю еще один вариант для тех, кто уже может использовать библиотеку Underscore.js в своем script. Underscore.js имеет функцию isArray() (см. http://underscorejs.org/#isArray).
_.isArray(object)
Возвращает true, если объект является массивом.
Если вы используете Angular, вы можете использовать функцию angular.isArray()
var myArray = [];
angular.isArray(myArray); // returns true
var myObj = {};
angular.isArray(myObj); //returns false
В Crockford JavaScript Хорошие части существует функция проверки, является ли данный аргумент массивом:
var is_array = function (value) {
return value &&
typeof value === 'object' &&
typeof value.length === 'number' &&
typeof value.splice === 'function' &&
!(value.propertyIsEnumerable('length'));
};
Он объясняет:
Сначала мы спрашиваем, правно ли это значение. Мы делаем это, чтобы отклонить нулевые и другие значения фальши. Во-вторых, мы спрашиваем, является ли typeof значением "object". Это будет верно для объектов, массивов и (странно) null. В-третьих, мы спрашиваем, имеет ли значение свойство length, которое является числом. Это всегда будет верно для массивов, но обычно это не для объектов. В-четвертых, мы спрашиваем, содержит ли значение метод сращивания. Это снова будет верно для всех массивов. Наконец, мы спрашиваем, является ли свойство length перечислимым (длина будет создаваться с помощью цикла for for?). Это будет ложно для всех массивов. Это самый надежный тест на массивность, который я нашел. К сожалению, это так сложно.
Универсальное решение ниже:
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
Я использовал эту строку кода:
if (variable.push) {
// variable is array, since AMAIK only arrays have push() method.
}
упомянутый 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([]);
Я создал этот немного кода, который может возвращать истинные типы.
Я пока не уверен в производительности, но это попытка правильно идентифицировать typeof.
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 == Массив - лучший способ. Его почти в 20 раз быстрее, чем использование toString(). Если вы расширяете объекты своими собственными конструкторами и хотите, чтобы эти творения считались "объектами", а это не работает, но в противном случае его путь быстрее. typeof так же быстро, как и метод конструктора, но typeof [] == 'object' возвращает true, что часто будет нежелательным. http://jsperf.com/constructor-vs-tostring
Следует отметить, что null.constructor выдает ошибку, поэтому, если вы можете проверить нулевые значения, вам нужно будет сначала сделать, если (testThing! == null) {}
function isArray(x){
return ((x != null) && (typeof x.push != "undefined"));
}
Так как свойство .length является специальным для массивов в javascript, вы можете просто сказать
obj.length === +obj.length // true if obj is an array
Underscorejs и несколько других библиотек используют этот короткий и простой трюк.
Что-то, с чем я только что придумал:
if (item.length)
//This is an array
else
//not an array