Bir nesnenin dizi olup olmadığını nasıl kontrol edebilirim?


2752

Dizelerin listesini veya tek bir dizeyi kabul eden bir işlev yazmaya çalışıyorum. Bir dize ise, o zaman sadece bir öğe ile bir diziye dönüştürmek istiyorum, bu yüzden bir hata korkusu olmadan üzerinde döngü olabilir.

Peki, değişkenin bir dizi olup olmadığını nasıl kontrol ederim?


Aşağıdaki çeşitli çözümleri tamamladım ve bir jsperf testi oluşturdum . Hepsi hızlı, bu yüzden sadece kullanın Array.isArray- şimdi iyi destekleniyor ve çerçevelerde çalışıyor .


6
'Nesne bir dizi olup olmadığını kontrol etmek' anlamına geldiğini düşündüm, ama 'nesne dizeleri bir dizi mi yoksa tek bir dize mi' kontrol etmek istiyorum. Görüp görmediğinizden emin değil misiniz? Yoksa sadece ben miyim? Ben daha fazla gibi şeyler düşünüyordum bu ben kimse burada bir şey eksik ...?
rr1g0

149
TL; DR - arr.constructor === Arrayen hızlısıdır.
Neta

3
jsben.ch/#/QgYAV - en yaygın yollar için bir kriter
EscapeNetscape

39
TL; DR - Dizi. ES5'ten beri isArray (dizi) ; ve $. jQuery içinde isArray (arr) .
Ondra Žižka

6
Unutmayın ki herhangi bir sebepten dolayı prototip üzerinden kurucunuzun üzerine yazarsanız bu arr.constructor === Arraytest yanlış olacaktır. Array.isArray(arr)yine de doğru döner.
ghaschel

Yanıtlar:


977

Modern tarayıcılarda şunları yapabilirsiniz:

Array.isArray(obj)

( Tarafından desteklenen Chrome 5, Firefox 4.0, IE 9, Opera 10.5 ve Safari 5)

Geriye dönük uyumluluk için aşağıdakileri ekleyebilirsiniz

# 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 kullanıyorsanız jQuery.isArray(obj)veya kullanabilirsiniz $.isArray(obj). Alt çizgi kullanırsanız,_.isArray(obj)

Farklı karelerde oluşturulan dizileri algılamanız gerekmiyorsa, yalnızca instanceof

obj instanceof Array

9
İşte destekleyen daha kapsamlı bir listeArray.isArray
lightswitch05

if (typeof Array.isArray === 'undefined') {olarak değiştirilebilirif(!Array.isArray) {
iMatoria

Ne için 's değerinde Object.prototype.string.call(obj)nesne varsa sahte olabilir Symbol.toStringTagüzerinde. Bu, gönderilen herhangi bir ortamın farkında Symbol.toStringTagolmadığımı ancak bunun Array.isArraygüvenli görünmediğini söyledi.
Benjamin Gruenbaum

5
instanceof ArrayDizi farklı bir çerçeveden geliyorsa neden başarısız oluyor?
NobleUplift

16
@NobleUplift: instanceof Arraydizi farklı bir çerçeveden geliyorsa başarısız olur, çünkü o farklı çerçevedeki her dizi farklı bir kurucuya Arrayve prototipe sahiptir. Uyumluluk / güvenlik nedenleriyle, her çerçevenin kendi küresel ortamı vardır ve buna küresel nesneler de dahildir. ObjectBir çerçeveden küresel farklıdır Objectbirbirinden küresel. ArrayKüreseller için de öyle . Axel Rauschmayer bu konuda daha fazla konuşuyor .
jschoi

1943

ECMAScript standardında verilen Object sınıfını bulmak için kullanılan toStringmetodu kullanmaktır Object.prototype.

if( Object.prototype.toString.call( someVar ) === '[object Array]' ) {
    alert( 'Array!' );
}

Veya typeofbunun bir String olup olmadığını test etmek için kullanabilirsiniz :

if( typeof someVar === 'string' ) {
    someVar = [ someVar ];
}

Veya performansla ilgili endişeleriniz yoksa concat, yeni bir boş Dizi için bir işlem yapabilirsiniz .

someVar = [].concat( someVar );

Doğrudan sorgulayabileceğiniz kurucu da var:

if (somevar.constructor.name == "Array") {
    // do something
}

Bir göz atın kapsamlı tedavi dan @TJ Crowder'ın aşağıda onun yorumunda yayınlanmıştır olarak, blog.

Hangi yöntemin daha iyi performans gösterdiğine dair bir fikir edinmek için bu karşılaştırmaya göz atın : http://jsben.ch/#/QgYAV

Gönderen @Bharath soru sorulduğunda için ES6 kullanarak diziye dönüştürme dizesi:

const convertStringToArray = (object) => {
   return (typeof object === 'string') ? Array(object) : object 
}

varsayalım:

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']

65
+1 Evet, toStringgitmenin yollarından biri. Burada biraz toplantım var: blog.niftysnippets.org/2010/09/say-what.html
TJ Crowder

3
typeof new String('beans') > 'nesne'
Ben

16
"[Object Array]" yazmak istemiyorsanız, Object.prototype.toString.call (someVar) === Object.prototype.toString.call ([]) kullanın ya da yazmazsanız kolaylık sağlama işlevini yapın Object.prototype.toString.call yazmak istemiyor
Pramod

13
'Modern tarayıcılarda' (yani IE9 + ve diğer herkes) çalışan vanilya Array.isArray kullanıyorum. Eski tarayıcı desteği için MDN geliştiricisinin
David Gilbertson

21
Modern dünyada yaşamak -Array.isArray(obj)
mcfedr

1274

İlk olarak uygulamanızın destekleyip desteklemediğini kontrol ederim isArray:

if (Array.isArray)
    return Array.isArray(v);

instanceofOperatörü kullanmayı da deneyebilirsiniz

v instanceof Array

127
v instanceof Arrayvbaşka bir çerçevede oluşturulmuşsa false değerini döndürür v( thatFrame.contentWindow.Arraysınıf örneğidir ).
pepkin88

47
Spesifik olarak: Array.isArrayECMAScript 5 / Javascript 1.8.5'in bir parçası olarak tanımlanır.
jevon

8
Gerçekten basit ve temiz bir çözüm AMA isArray bazı eski tarayıcılarla (eski IE7 ve IE8) uyumlu değildir. Kaynak: kangax.github.io/es5-compat-table/#
Wookie88

2
Nasıl olur: if (Array.isArray) Array.isArray (v) döndürürse; başka Array v instanceof döndürür;
lewdev

1
ya da sadece:return (Array.isArray && Array.isArray(v)) || (v instanceof Array);
Stijn de Witt

298

jQuery ayrıca bir $.isArray()yöntem sunar :

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>


27
Sadece bir not, jQuery toString yöntemini dahili olarak kullanır: GitHub Source
Jacob Squires

5
@JacobSaat bağlıdır. Az önce burada test ettim, Chrome'daki en son jQuery - $.isArray === Array.isArraydoğru çıkıyor.
Renan

3
@Renan: Bu jQuery kullanmakla ilgili iyi bir şey. Genellikle bunu yapmak için en modern ve en iyi yöntemi kullanır ve ne kullanacağınızı öğrenmek için kendinizi kontrol eden tüm özellikleri yapmanız gerekmez.
huşu

jQuery Array.isArrayperde arkasında kullanıyor : github.com/jquery/jquery/blob/master/src/core.js#L211
Sergiu

1
Ama hiç kimse bu işlevi jQuery JUST FOR kullanmayacak, değil mi? Ben sadece bir şey dizi olup olmadığını kontrol etmek istiyorum çünkü jquery indirmek olmaz: p
Automagisch

106

Bu, tüm yöntemler arasında en hızlı olanıdır (tüm tarayıcılar desteklenir):

function isArray(obj){
    return !!obj && obj.constructor === Array;
}

2
Haklısın, bu soruya dahil ettiğim testlere göre en hızlısı.
mpen

5
Bu yöntemi kullanmanın bir dezavantajı var mı? Kabul edilen üst yanıttan çok daha basit ve etkili görünüyor.
David Meza

@shinobi - sadece meraklı (ve bunu sık sık gördüm) - durumu neden if (obj && Array === obj.constructor)aksine ifade ediyorsunuz if (obj && obj.constructor === Array)? İngilizceye çeviride kayıp, daha sonra bir şeyi kodlamak mı? Örneğin, İngilizce konuşanlar genellikle "nesne var mı ve yapıcısı dizi sınıfından mı geliyor?" veya teknik bir nedeni var mı?
senkronize olmayan

function object_type(o){var t = typeof(o);return ((t==="object") && (o.constructor===Array)) ? "array" : t;} /*allows you to */ switch(object_type(o)){ case 'array': break; case 'object' : o.dosomething();}
senkronize olmayan

3
@shinobi hepsi iyi. güvenli bir c alışkanlık bir kalıntı olabilir varsayalım - yanlışlıkla = yerine == kullanırsanız, onun atanabilir bir değişken olarak derlemek olmaz.
senkronize olmayan

47

Aşağıda bu diziye sahip olduğunuzu düşünün :

var arr = [1,2,3,4,5];

Javascript (yeni ve eski tarayıcılar):

function isArray(arr) {
  return arr.constructor.toString().indexOf("Array") > -1;
}

veya

function isArray(arr) {
  return arr instanceof Array;
}

veya

function isArray(arr) {
  return Object.prototype.toString.call(arr) === '[object Array]';
}

sonra şöyle deyin:

isArray(arr);

Javascript (IE9 +, Ch5 +, FF4 +, Saf5 +, Opera10.5 +)

Array.isArray(arr);

jQuery:

$.isArray(arr);

Açısal:

angular.isArray(arr);

Alt Çizgi ve Lodash:

_.isArray(arr);

34

Array.isArray hızlı çalışır, ancak tüm tarayıcı sürümleri tarafından desteklenmez. Böylece başkaları için bir istisna yapabilir ve evrensel yöntemi kullanabilirsiniz:

    Utils = {};    
    Utils.isArray = ('isArray' in Array) ? 
        Array.isArray : 
        function (value) {
            return Object.prototype.toString.call(value) === '[object Array]';
        }

3
.toString()Yöntemi almanız gerekiyor Object.prototype. Şu anda window.toString()aynı olanı kullanıyorsunuz .
sistem

Haklısın. window.toStringaynısını Object.prototype.toStringChrome'daki gibi yapın.
CruorVult

isArray hiç hızlı değil. En yavaş yöntemdir.
jemiloii

Neden onu Utils yerine Array'a eklemiyorsun? (Yeni dizi nesnelerinde ekstra özellikler istemediğinizi biliyorum, ancak bunun yalnızca Array.prototype'a isArray eklerseniz olacağını düşünüyorum.)
David Winiecki

27

Bunu kontrol etmek için basit işlev:

function isArray(object)
{
    return object.constructor === Array;
}

16
Bunu bir satıra indirirdim return object.constructor === Array- ama bunun sadece diziler için doğru olacağından emin misin?
mpen

12
Bunu tüm boole ifadeleriyle yapabilir. Gördüğümde beni deli ediyor if(x) return true; else return false:-) Geri olsa bile, ifadeyi reddetmelisin.
mpen

3
Bunun getElementsByTagName için true değerini döndürmemesinin nedeni, bu işlevin sonucunun aslında bir dizi değil bir HTMLCollection olmasıdır.
Yuval A.

6
Nesne tanımsız veya boşsa, bu kötü bir şekilde başarısız olur.
John Henckel

1
@JohnHenckel Cevabımı görün stackoverflow.com/a/29400289/34806 Hem endişenizi hem de ilk yorumu dikkate alıyor, hepsi bir satırda
Dexygen

17

MDN'nin burada söylediği gibi :

normal nesneleri dizilerden ayırmak için Array.isArray veya Object.prototype.toString.call kullanın

Bunun gibi:

  • Object.prototype.toString.call(arr) === '[object Array]'veya

  • Array.isArray(arr)


17

Bu soru için sadece bir satır çözüm var

x instanceof Array

burada x değişkendir, x bir dizi ise true, değilse false döndürür.


Çok daha temiz ve gelecekteki güvenli! Bu ya da bir typeofkarşılaştırma.
ChristoKiwi

Bu, iyi miktarda tarayıcı desteği alan bir şey mi? Bunu sevdim.
Dan Zuzevich

1
Ne yazık ki, bu bir try / catch olmadan aslında kullanışlı değildir, çünkü "x" bir dizi gibi bir nesne ise {}, sözdizimi hatası alırsınız.
abalter

15

Değişkeninizin türünü bir dizi olup olmadığını kontrol edebilirsiniz;

var myArray=[];

if(myArray instanceof Array)
{
....
}

1
Birkaç kişi daha önce bahsetti instanceof.. Sanırım birkaç garip senaryo altında başarısız oluyor.
mpen

15

Karşılaştığınız nesnenin türünü test etmek için bir işlev yapardım ...

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

o zaman basit bir if ifadesi yazabilirsiniz ...

if(whatAmI(myVar) === "Array"){
    // do array stuff
} else { // could also check `if(whatAmI(myVar) === "String")` here to be sure
    // do string stuff
}

12

Bunu çok basit bir şekilde yapıyorum. Benim için çalışıyor. Herhangi bir dezavantajı var mı?

Array.prototype.isArray = true;

a=[]; b={};
a.isArray  // true
b.isArray  // (undefined -> false)

7
kandırdım{isArray:true}
Bergi

JSON.parse(someDataFromElsewhere).items.isArray(verilere bağlı olarak) true değerini döndürebilir ve kodunuzu kırabilir.
Roy Tinker

12

Bu, yorumları dikkate alarak bu cevabı geliştirmeye çalışıyorum :

var isArray = myArray && myArray.constructor === Array;

İf / else komutundan kurtulur ve dizinin boş veya tanımsız olma olasılığını açıklar


yapıcı ES5'te mevcut değil
TechTurtle


11

Hata kontrolü gibi iki alternatif yöntemle jsperf keman güncelledik .

'Nesne' ve 'Dizi' prototiplerinde sabit bir değer tanımlayan yöntemin diğer yöntemlerden daha hızlı olduğu ortaya çıkıyor. Biraz şaşırtıcı bir sonuçtur.

/* 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/>");

Değişken tanımsız değeri alıyorsa bu iki yöntem işe yaramaz, ancak bir değere sahip olduğundan eminseniz işe yarar. Bir değerin bir dizi mi yoksa tek bir değer mi olduğunu göz önünde bulundurarak performansı kontrol etmekle ilgili olarak, ikinci yöntem geçerli bir hızlı yöntem gibi görünür. Chrome'daki 'instanceof' den biraz daha hızlı, Internet Explorer, Opera ve Safari'de (makinemde) en iyi ikinci yöntemden iki kat daha hızlı.


9

İnsanların bir çeşit çiğ javascript yaklaşımı aradıklarını biliyorum. Ancak daha az düşünmek istiyorsanız, buraya bir göz atın: http://underscorejs.org/#isArray

_.isArray(object) 

Nesne bir Dizi ise true değerini döndürür.

(function(){ return _.isArray(arguments); })();
=> false
_.isArray([1,2,3]);
=> true

7
"Bir çerçeve / kütüphane için başka bir etiket de eklenmedikçe, saf bir JavaScript cevabı beklenir."
Michał Perłakowski

5

Gördüğüm en iyi çözüm, typeof için çapraz tarayıcı değiştirme. Angus Croll'un çözümünü buradan kontrol edin .

TL; DR sürümü aşağıdadır, ancak makale konuyla ilgili harika bir tartışmadır, bu nedenle zamanınız varsa okumalısınız.

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 */};

5

İşte tembel yaklaşımım:

if (Array.prototype.array_ === undefined) {
  Array.prototype.array_ = true;
}

// ...

var test = [],
    wat = {};

console.log(test.array_ === true); // true
console.log(wat.array_ === true);  // false

Ben prototip "karışıklık" için kutsal olduğunu biliyorum, ama önerilen toStringyöntemden önemli ölçüde daha iyi performans gibi görünüyor .

Not: Bu yaklaşımın bir dezavantajı, sınırlar arasında çalışmayacaktıriframe , ancak kullanım durumum için bu bir sorun değildir.


performans açısından daha iyi değil, en azından Ubuntu 64-
bit'de FF30

2
wat = {array_: true}nesneler tarafından kandırılmış .
Bergi

@Bergi: Evet, bu açık olmalı. Eğer ayarlıyorsan obj.array_ = true, sadece kendini kandırıyorsun .
namuol

@namuol: Kendimi kandırmak zorunda değilim. Genellikle yeterli nesne sözlük olarak kullanılır. cacheArama dizelerini özellik anahtarları olarak kullanan arama sonuçlarını kaydetmek için bir nesneyi düşünün . Bir kullanıcı ararsa ne olur array_? Nesneniz bundan dolayı bir dizi haline geliyor mu? Bu sadece bir hata.
Bergi

@namuol: Ayrıca, bu yaklaşım ilgili tüm tarafların (kullanılmış kütüphaneler dahil) .array_dizileri etiketlemek için kullanıldığını kabul etmelerini gerektirecektir . Burada durum böyle değil, bir .arrayşey ifade edebilir. En azından açıklayıcı bir dize kullanmalı ve rasgele kullanımın uygunsuzluğunu göstermelisiniz, örn .__isArray = true.
Bergi

5

Stoyan Stefanov'un ECMAScript 5 yöntemi Array.isArray () yöntemini kullanmanın yanı sıra olası tüm sorunları ele alması gereken JavaScript Kalıpları kitabında güzel bir örnek var .

İşte burada:

if (typeof Array.isArray === "undefined") {
    Array.isArray = function (arg) {
        return Object.prototype.toString.call(arg) === "[object Array]";
    };
}

Bu arada, jQuery kullanıyorsanız, bu yöntemi $ .isArray () kullanabilirsiniz


2
+1: neden sadece basit değil if(!Array.isArray) {... ?
Marco Demaio

5

bir Nesnenin Dizi olup olmadığını kontrol etmenin en kolay ve en hızlı yolu.

 var arr = [];
  arr.constructor.name ==='Array'  //return true;

veya

arr.constructor ===Array //return true;

veya bir yardımcı program işlevi yapabilirsiniz:

function isArray(obj){ return obj && obj.constructor ===Array}

kullanımı:

isArray(arr); //return true

5

Nesnenizin bir concat yöntemi olmadığını biliyorsanız, aşağıdakiler kullanılabilir.

var arr = [];
if (typeof arr.concat === 'function') {
    console.log("It's an array");
}


Bu iyi bir hile, ama geçersiz kılınabilir ... ama çoğu zaman sonuç almalı
Alireza

5

Eğer isArray yöntemi olabilir ama ben ile kontrol etmeyi tercih ederim

Object.getPrototypeOf(yourvariable) === Array.prototype


Bunu neden tercih edesin?
mpen

@mpen Object.getPrototypeOf(yourvariable)bir Array nesnesinin prototipini döndürür. Ve kod güvenmek en hızlı ve güvenlidir.
ÇELİK

1
Folyo yapmak kolaydır: pastebin.com/MP8d5bCE Ayrıca, "en hızlı" iddianızı yedeklemek için performans testleriniz var mı?
18'de

4

Bu işleve iletilebilecek yalnızca iki tür değer bir dize veya bir dize dizisiyse, basit tutun typeofve dize olasılığı için bir denetim kullanın :

function someFunc(arg) {
    var arr = (typeof arg == "string") ? [arg] : arg;
}

Evet ... bu senaryo için işe yarar, ama genel olarak değil. Yine de varargs kullanarak sona erdi. :)
20'de mpen

4
A = [1,2,3]
console.log(A.map==[].map)

En kısa versiyonu bulmak için burada şimdiye kadar aldım.

Unutmayın, her zaman olası tüm kombinasyonları algılayacak mükemmel bir fonksiyon yoktur. Aletlerinizin tüm yeteneklerini ve sınırlarını bilmek sihirli bir araç beklemekten daha iyidir.


1
benim küçük bir türetme A.map !== undefinedama evet, bu maymun
patchers dünyasında kaygan

Bilginize: Bu
iFrames'te

4
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))


4

Bunu deneyebilirsiniz:

var arr = []; (or) arr = new Array();
var obj = {}; (or) arr = new Object();

arr.constructor.prototype.hasOwnProperty('push') //true

obj.constructor.prototype.hasOwnProperty('push') // false

4

Bu işlev neredeyse her şeyi bir diziye dönüştürür:

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]"
}

Bazı yeni tarayıcı özelliklerini kullanır, böylece maksimum destek için bunu çoklu doldurmak isteyebilirsiniz.

Örnekler:

> 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 dizeleri, bir dizi karakter yerine tek bir öğeye sahip bir diziye dönüştürülecektir. SilisString tercih edip etmeyeceğinizi .

Array.isArrayBurada kullandım çünkü en sağlam ve aynı zamanda en basit olanı.


4

Sizin durumunuzda , dizi (ve hatta birleştirilmiş) kadar tek nesneleri de kabul edebilen Arrayconcat yöntemini kullanabilirsiniz :

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 Array'ın en eski yöntemlerinden biri gibi görünüyor (hatta IE 5.5 bunu iyi biliyor).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.