Как проверить, является ли объект массивом?
-
23-10-2019 - |
Вопрос
Я пытаюсь написать функцию, которая либо принимает список строк, либо одну строку. Если это строка, то я хочу преобразовать ее в массив только с одним элементом. Тогда я могу пройти через это, не опасаясь ошибки.
Итак, как мне проверить, является ли переменная массивом?
Я собрал различные решения ниже и создал JSperf Test.
Решение
В современных браузерах вы можете сделать
Array.isArray(obj)
(При поддержке Chrome 5, Firefox 4.0, IE 9, Opera 10.5 и Safari 5)
Для обратной совместимости вы можете добавить следующее
# 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
Другие советы
Метод, приведенный в стандарте ECMASCRIPT, чтобы найти класс объекта, заключается в использовании toString
Метод от Object.prototype
.
if( Object.prototype.toString.call( someVar ) === '[object Array]' ) {
alert( 'Array!' );
}
Или вы можете использовать typeof
Чтобы проверить, является ли это строкой:
if( typeof someVar === 'string' ) {
someVar = [ someVar ];
}
Или если вы не обеспокоены производительностью, вы можете просто сделать concat
в новый пустой массив.
someVar = [].concat( someVar );
Есть также конструктор, который вы можете напрямую запросить:
if (somevar.constructor.name == "Array") {
// do something
}
Проверьте тщательное лечение из @TJ Crowder's Блог, как опубликовано в его комментарии ниже.
Проверьте это эталон Чтобы получить представление, какой метод работает лучше: http://jsben.ch/#/qgyav
Из @Bharath преобразовать строку в массив с помощью ES6 для задания:
const convertStringToArray = (object) => {
return (typeof object === 'string') ? Array(object) : object
}
предполагать:
let m = 'bla'
let n = ['bla','Meow']
let y = convertStringToArray(m)
let z = convertStringToArray(n)
console.log('check y: '+JSON.stringify(y)) . // check y: ['bla']
console.log('check y: '+JSON.stringify(z)) . // check y: ['bla','Meow']
Я бы сначала проверил, поддерживает ли ваша реализация isArray
:
if (Array.isArray)
return Array.isArray(v);
Вы также можете попробовать использовать instanceof
оператор
v instanceof Array
jQuery также предлагает $.isArray()
Метод:
var a = ["A", "AA", "AAA"];
if($.isArray(a)) {
alert("a is an array!");
} else {
alert("a is not an array!");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Это самый быстрый среди всех методов (все браузеры поддерживаются):
function isArray(obj){
return !!obj && obj.constructor === Array;
}
Представьте, что у вас есть это массив ниже:
var arr = [1,2,3,4,5];
JavaScript (новые и старые браузеры):
function isArray(arr) {
return arr.constructor.toString().indexOf("Array") > -1;
}
или же
function isArray(arr) {
return arr instanceof Array;
}
или же
function isArray(arr) {
return Object.prototype.toString.call(arr) === '[object Array]';
}
Тогда назовите это так:
isArray(arr);
JavaScript (IE9+, CH5+, FF4+, SAF5+, Opera10.5+)
Array.isArray(arr);
jQuery:
$.isArray(arr);
Угловой:
angular.isArray(arr);
Подчеркивание и Лодаш:
_.isArray(arr);
Array.isarray работает быстро, но он не поддерживается всеми версиями браузеров. Таким образом, вы можете сделать исключение для других и использовать универсальный метод:
Utils = {};
Utils.isArray = ('isArray' in Array) ?
Array.isArray :
function (value) {
return Object.prototype.toString.call(value) === '[object Array]';
}
Простая функция, чтобы проверить это:
function isArray(object)
{
if (object.constructor === Array) return true;
else return false;
}
Как говорит MDN здесь:
использовать Array.isarray или же Object.prototype.tostring.call для дифференциации регулярных объектов от массивов
Как это:
Object.prototype.toString.call(arr) === '[object Array]'
, или жеArray.isArray(arr)
Есть только одно решение для этого вопроса
x instanceof Array
где x - переменная, она вернет true, если x - массив, а ложь, если это не так.
Вы можете проверить тип вашей переменной, будь то массив;
var myArray=[];
if(myArray instanceof Array)
{
....
}
Я бы сделал функцию, чтобы проверить тип объекта, с которым вы имеете дело ...
function whatAmI(me){ return Object.prototype.toString.call(me).split(/\W/)[2]; }
// tests
console.log(
whatAmI(["aiming","@"]),
whatAmI({living:4,breathing:4}),
whatAmI(function(ing){ return ing+" to the global window" }),
whatAmI("going to do with you?")
);
// output: Array Object Function String
Тогда вы можете написать простое, если оператор ...
if(whatAmI(myVar) === "Array"){
// do array stuff
} else { // could also check `if(whatAmI(myVar) === "String")` here to be sure
// do string stuff
}
Я делаю это очень просто. Работает на меня. Есть недостатки?
Array.prototype.isArray = true;
a=[]; b={};
a.isArray // true
b.isArray // (undefined -> false)
Это моя попытка улучшить этот ответ Принимая во внимание комментарии:
var isArray = myArray && myArray.constructor === Array;
Он избавляется от IF/else, и учитывает возможность того, что массив будет нулевым или неопределенным
https://developer.mozilla.org/en-us/docs/javascript/reference/global_objects/array/isarray
Array.isArray = Array.isArray || function (vArg) {
return Object.prototype.toString.call(vArg) === "[object Array]";
};
Я обновил JSperf Fiddle с двумя альтернативными методами, а также проверкой ошибок.
Оказывается, что метод, определяющий постоянное значение в прототипах «объекта» и «массива», более быстрее, чем любой другой метод. Это несколько удивительный результат.
/* Initialisation */
Object.prototype.isArray = function() {
return false;
};
Array.prototype.isArray = function() {
return true;
};
Object.prototype._isArray = false;
Array.prototype._isArray = true;
var arr = ["1", "2"];
var noarr = "1";
/* Method 1 (function) */
if (arr.isArray()) document.write("arr is an array according to function<br/>");
if (!noarr.isArray()) document.write("noarr is not an array according to function<br/>");
/* Method 2 (value) - **** FASTEST ***** */
if (arr._isArray) document.write("arr is an array according to member value<br/>");
if (!noarr._isArray) document.write("noarr is not an array according to member value<br/>");
Эти два метода не работают, если переменная берет неопределенное значение, но они работают, если вы уверены, что у них есть значение. Что касается проверки с учетом производительности, если значение является массивом или одним значением, второй метод выглядит как действительный быстрый метод. Это немного быстрее, чем «экземпляр» на Chrome, в два раза быстрее, чем второй лучший метод в Internet Explorer, Opera и Safari (на моей машине).
Я знаю, что люди ищут какой -то сырой подход JavaScript. Но если вы хотите думать меньше, посмотрите здесь: http://underscorejs.org/#isarray
_.isArray(object)
Возвращает True, если объект является массивом.
(function(){ return _.isArray(arguments); })();
=> false
_.isArray([1,2,3]);
=> true
Лучшее решение, которое я видел,-это поперечная замена для TypeOF. Проверьте решение Angus Croll здесь.
Версия TL; DR ниже, но статья - отличное обсуждение проблемы, поэтому вы должны прочитать его, если у вас есть время.
Object.toType = function(obj) {
return ({}).toString.call(obj).match(/\s([a-z|A-Z]+)/)[1].toLowerCase();
}
// ... and usage:
Object.toType([1,2,3]); //"array" (all browsers)
// or to test...
var shouldBeAnArray = [1,2,3];
if(Object.toType(shouldBeAnArray) === 'array'){/* do stuff */};
Вот мой ленивый подход:
if (Array.prototype.array_ === undefined) {
Array.prototype.array_ = true;
}
// ...
var test = [],
wat = {};
console.log(test.array_ === true); // true
console.log(wat.array_ === true); // false
Я знаю, что это кощунство, чтобы «связываться с» прототипом, но Похоже, работает значительно лучше, чем рекомендуется toString
метод.
Примечание: Подводной камень этого подхода в том, что это не будет работать через iframe
границы, но для моего варианта использования это не проблема.
В книге Стояна Стефанова есть хороший пример JavaScript Patterns которые предполагают, чтобы решить все возможные проблемы, а также использовать метод Ecmascript 5 Array.isarray ().
Итак, вот это:
if (typeof Array.isArray === "undefined") {
Array.isArray = function (arg) {
return Object.prototype.toString.call(arg) === "[object Array]";
};
}
Кстати, если вы используете jQuery, вы можете использовать его метод $ .isarray ()
Самый простой и быстрый способ проверить, является ли объект массивом или нет.
var arr = [];
arr.constructor.name ==='Array' //return true;
или же
arr.constructor ===Array //return true;
или вы можете сделать функцию утилиты:
function isArray(obj){ return obj && obj.constructor ===Array}
Применение:
isArray(arr); //return true
Следующее может быть использовано, если вы знаете, что у вашего объекта нет метода CONCAT.
var arr = [];
if (typeof arr.concat === 'function') {
console.log("It's an array");
}
Вы могли бы - это метод Isarray, но я бы предпочел проверить с
Object.getPrototypeOf(yourvariable) === Array.prototype
Если только два вида значений, которые могут быть переданы в эту функцию, являются строкой или массивом строк, сохраняйте ее и используйте typeof
Проверьте возможность строки:
function someFunc(arg) {
var arr = (typeof arg == "string") ? [arg] : arg;
}
A = [1,2,3]
console.log(A.map==[].map)
В поисках самой короткой версии, вот что я получил до сих пор.
Обратите внимание, что нет идеальной функции, которая всегда будет обнаружить все возможные комбинации. Лучше знать все способности и ограничения ваших инструментов, чем ожидать магического инструмента.
function isArray(value) {
if (value) {
if (typeof value === 'object') {
return (Object.prototype.toString.call(value) == '[object Array]')
}
}
return false;
}
var ar = ["ff","tt"]
alert(isArray(ar))
Простая функция для тестирования, если входное значение является массивом, является следующей:
function isArray(value)
{
return Object.prototype.toString.call(value) === '[object Array]';
}
Это работает Cross Browser, и со старыми браузерами. Это вытащен из сообщения в блоге TJ Crowders
Вы можете попробовать это:
var arr = []; (or) arr = new Array();
var obj = {}; (or) arr = new Object();
arr.constructor.prototype.hasOwnProperty('push') //true
obj.constructor.prototype.hasOwnProperty('push') // false
Эта функция превратит практически все в массив:
function arr(x) {
if(x === null || x === undefined) {
return [];
}
if(Array.isArray(x)) {
return x;
}
if(isString(x) || isNumber(x)) {
return [x];
}
if(x[Symbol.iterator] !== undefined || x.length !== undefined) {
return Array.from(x);
}
return [x];
}
function isString(x) {
return Object.prototype.toString.call(x) === "[object String]"
}
function isNumber(x) {
return Object.prototype.toString.call(x) === "[object Number]"
}
Он использует некоторые новые функции браузера, так что вы можете захотеть полифиль это для максимальной поддержки.
Примеры:
> arr(null);
[]
> arr(undefined)
[]
> arr(3.14)
[ 3.14 ]
> arr(1/0)
[ Infinity ]
> gen = function*() { yield 1; yield 2; yield 3; }
[Function: gen]
> arr(gen())
[ 1, 2, 3 ]
> arr([4,5,6])
[ 4, 5, 6 ]
> arr("foo")
[ 'foo' ]
Строки NB будут преобразованы в массив с одним элементом вместо массива ChARS. Удалить isString
Проверьте, предпочтет ли вы это наоборот.
Я использовал Array.isArray
Здесь потому что это самый надежный а также проще.
В вашем случае вы можете использовать concat
метод Множество которые могут принимать отдельные объекты, а также массив (и даже объединен):
function myFunc(stringOrArray)
{
var arr = [].concat(stringOrArray);
console.log(arr);
arr.forEach(function(item, i)
{
console.log(i, "=", item);
})
}
myFunc("one string");
myFunc(["one string", "second", "third"]);
concat
Похоже, что один из старейших методов массива (даже IE 5.5 хорошо это знает).