Aș dori să verific dacă o variabilă este fie o matrice, fie o singură valoare în JavaScript.
Am gasit o posibila solutie...
if (variable.constructor == Array)...
Este acesta cel mai bun mod în care se poate face acest lucru?
Aș dori să verific dacă o variabilă este fie o matrice, fie o singură valoare în JavaScript.
Am gasit o posibila solutie...
if (variable.constructor == Array)...
Este acesta cel mai bun mod în care se poate face acest lucru?
Există mai multe moduri de a verifica dacă o variabilă este o matrice sau nu. Cea mai bună soluție este cea pe care ați ales-o.
variable.constructor === Array
Aceasta este cea mai rapidă metodă de pe Chrome și, cel mai probabil, pentru toate celelalte browsere. Toate tablourile sunt obiecte, așa că verificarea proprietății constructorului este un proces rapid pentru motoarele JavaScript.
Dacă întâmpinați probleme cu a afla dacă o proprietate a obiectelor este o matrice, trebuie mai întâi să verificați dacă proprietatea este acolo.
variable.prop && variable.prop.constructor === Array
Alte moduri sunt:
Array.isArray(variable)
Actualizare 23 mai 2019 folosind Chrome 75, strigă lui @AnduAndrici pentru că m-a pus să revin cu întrebarea lui Aceasta din urmă este, după părerea mea, cea mai urâtă și este una dintre cele mai lente cel mai rapid. Rulează cu aproximativ 1/5 din viteza ca primul exemplu. Acest tip este cu aproximativ 2-5% mai lent, dar este destul de greu de spus. Solid de folosit! Destul de impresionat de rezultat. Array.prototype, este de fapt o matrice. puteți citi mai multe despre el aici https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
variable instanceof Array
Această metodă rulează aproximativ 1/3 din viteza ca prim exemplu. Încă destul de solid, arată mai curat, dacă ești despre cod frumos și nu atât de performanță. Rețineți că verificarea numerelor nu funcționează, deoarece variable instanceof Number
returnează întotdeauna false
. Actualizare: instanceof
acum atinge 2/3 din viteza!
Deci încă o actualizare
Object.prototype.toString.call(variable) === '[object Array]';
Acest tip este cel mai lent pentru a încerca să verifice un Array. Cu toate acestea, acesta este un magazin unic pentru orice tip pe care îl căutați. Cu toate acestea, deoarece căutați o matrice, utilizați cea mai rapidă metodă de mai sus.
De asemenea, am făcut un test: http://jsperf.com/instanceof-array-vs-array-isarray/35 Așa că distrează-te puțin și verifică-l.
Notă: @EscapeNetscape a creat un alt test, deoarece jsperf.com este oprit. http://jsben.ch/#/QgYAV Am vrut să mă asigur că link-ul original rămâne oricând jsperf revine online.
variable && variable.constructor === Array
pentru a vă asigura că variabila nu este nulă sau nedefinită.
- person jemiloii; 12.01.2015
!!~variable.constructor.toString().indexOf('Array()')
, variable.constructor.toString() == Array().constructor.toString()
(probabil va fi puțin lentă) și Object.prototype.toString.call(variable) == '[object Array]'
- person Ismael Miguel; 26.03.2015
variable && variable.constructor
. De asemenea, rețineți că 5 instanceof Number
nu funcționează conform așteptărilor. În cazul în care arată prototipul, numerele nu au un prototip, cu excepția cazului în care setați unul. Numerele au constructori.
- person jemiloii; 16.03.2016
instanceof
nu le folosește. Ceea ce este ciudat pentru că, este singurul scop, potrivit MDN...
- person jemiloii; 16.03.2016
variable && variable.constructor === Array
- person jemiloii; 05.10.2016
Array.isArray(variable)
nici măcar nu a funcționat pentru mine. Primul s-a descurcat excelent!
- person awe; 20.09.2017
Array.isArray
este cel mai rapid, nu cel mai lent
- person Ferrybig; 25.09.2017
instanceof
este optimizat pe aceeași cale. În mod amuzant, comparația .constructor
este mai lentă. Întregul punct al lui isArray
este oricum între tărâmuri (matrice trecute între cadre și contexte).
- person Benjamin Gruenbaum; 06.07.2018
variable.constructor === Array
în continuare răspunsul acceptat ca fiind cel mai rapid/cel mai performant? sau variable instanceof Array
sau Array.isArray(variable)
au devenit mai viabile? -- întrebând, deoarece răspunsurile/comentariile sunt destul de vechi în anumite locuri. Foarte apreciat :)
- person Andu Andrici; 21.05.2019
variable.constructor === Array
Dacă nu mai era cazul, l-aș fi actualizat și aș fi oferit un motiv pentru care am actualizat-o.
- person jemiloii; 31.07.2019
instanceof
rulează cu 2/3 din viteza răspunsului inițial. Asta înseamnă mai repede? Mai lent? Există o oarecare ambiguitate în formulare, deși, desigur, contextul paragrafului pare să indice mai lent. Am rulat câteva benchmark-uri proprii modificând codul din jsben.ch/QgYAV, dar acele rezultate sugerau că instanceof
a fost cel mai rapid . Într-o notă similară, jsben.ch/QgYAV se leagă acum la un benchmark gol.
- person Sebastian Gaweda; 31.07.2019
De asemenea, ai putea folosi:
if (value instanceof Array) {
alert('value is Array!');
} else {
alert('Not an array');
}
Aceasta mi se pare o soluție destul de elegantă, dar pentru fiecare a lui.
Editați | ×:
Începând cu ES5 există acum și:
Array.isArray(value);
Dar acest lucru se va rupe pe browserele mai vechi, cu excepția cazului în care utilizați polyfills (în principiu... IE8 sau similar).
Array instanceof Object == true
.
- person Pierre; 29.11.2012
variable instanceof Object
, deoarece nu este o instanță a unui Array.
- person tuck; 01.05.2013
Array.prototype instanceof Array; // false
(ar trebui să fie adevărat); de asemenea ({ __proto__ : Array.prototype }) instanceof Array; // true
(ar trebui să fie fals)
- person vortexwolf; 04.11.2013
Array.isArray(arr)
- person Dominic; 13.10.2014
Există mai multe soluții cu propriile lor ciudatenii. Această pagină oferă o prezentare generală bună . O soluție posibilă este:
function isArray(o) {
return Object.prototype.toString.call(o) === '[object Array]';
}
Am observat că cineva a menționat jQuery, dar nu știam că există o funcție isArray()
. Se pare că a fost adăugat în versiunea 1.3.
jQuery îl implementează așa cum sugerează Peter:
isArray: function( obj ) {
return toString.call(obj) === "[object Array]";
},
După ce am pus deja multă încredere în jQuery (în special în tehnicile lor pentru compatibilitatea între browsere), fie voi face upgrade la versiunea 1.3 și voi folosi funcția lor (cu condiția ca actualizarea să nu cauzeze prea multe probleme), fie voi folosi această metodă sugerată direct în cod.
Multumesc mult pentru sugestii.
În browserele moderne (și în unele browsere vechi), puteți face
Array.isArray(obj)
(Supportat de Chrome 5, Firefox 4.0, IE 9, Opera 10.5 și Safari 5)
Dacă aveți nevoie să acceptați versiuni mai vechi de IE, puteți utiliza es5-shim pentru a polifill Array .isArray; sau adăugați următoarele
# 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]';
}
};
Dacă utilizați jQuery, puteți folosi jQuery.isArray(obj)
sau $.isArray(obj)
. Dacă folosești caracterul de subliniere, poți folosi _.isArray(obj)
Dacă nu aveți nevoie să detectați matricele create în cadre diferite, puteți utiliza și instanceof
obj instanceof Array
Notă: cuvântul cheie arguments
care poate fi folosit pentru a accesa argumentul unei funcții nu este un Array, chiar dacă (de obicei) se comportă ca unul:
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
acolo? Se pare că ar trebui să fie Object.prototype.toString.call
.
- person Brock; 20.11.2014
Aceasta este o întrebare veche, dar având aceeași problemă, am găsit o soluție foarte elegantă pe care vreau să o împărtășesc.
Adăugarea unui prototip la Array îl face foarte simplu
Array.prototype.isArray = true;
Acum, odată, dacă aveți un obiect pe care doriți să îl testați pentru a vedea dacă este o matrice, tot ce aveți nevoie este să verificați noua proprietate
var box = doSomething();
if (box.isArray) {
// do something
}
isArray este disponibil numai dacă este o matrice
Object.prototype.isArray = true;
! :(
- person ErikE; 30.09.2012
Array.isArray
este o metodă (de exemplu, Array.isArray([1,2,3]) === true
), așa că @ErikE nu era un troll. Aș evita să urmăresc acest răspuns, deoarece va sparge codul în unele browsere moderne.
- person JaredMcAteer; 11.07.2013
{}.isArray === true
cu soluția mea, care era ideea...
- person ErikE; 12.07.2013
Array.prototype["com.my.unique.name"].isArray
;)
- person SOFe; 28.12.2018
Prin Crockford:
function typeOf(value) {
var s = typeof value;
if (s === 'object') {
if (value) {
if (value instanceof Array) {
s = 'array';
}
} else {
s = 'null';
}
}
return s;
}
Principalul eșec menționat de Crockford este incapacitatea de a determina corect matricele care au fost create într-un context diferit, de exemplu, window
. Pagina respectivă are o versiune mult mai sofisticată dacă aceasta este insuficientă.
Dacă aveți de-a face doar cu EcmaScript 5 și mai sus, atunci puteți utiliza funcția încorporată Array.isArray
e.g.,
Array.isArray([]) // true
Array.isArray("foo") // false
Array.isArray({}) // false
Personal îmi place sugestia lui Peter: https://stackoverflow.com/a/767499/414784 (pentru ECMAScript 3. Pentru ECMAScript 5, utilizați Array.isArray()
)
Comentariile la postare indică, totuși, că, dacă toString()
este schimbat deloc, acest mod de a verifica o matrice va eșua. Dacă chiar doriți să fiți specific și să vă asigurați că toString()
nu a fost schimbat și nu există probleme cu atributul clasei obiectelor ([object Array]
este atributul clasei unui obiect care este o matrice), atunci vă recomand să faceți ceva de genul acesta:
//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;
}
}
Rețineți că în JavaScript The Definitive Guide a 6-a ediție, 7.10, se spune că Array.isArray()
este implementat folosind Object.prototype.toString.call()
în ECMAScript 5. De asemenea, rețineți că, dacă vă veți face griji cu privire la schimbarea implementării lui toString()
, ar trebui să vă faceți griji și cu privire la schimbarea tuturor celorlalte metode încorporate. . De ce să folosiți push()
? Cineva o poate schimba! O astfel de abordare este o prostie. Verificarea de mai sus este o soluție oferită celor îngrijorați de toString()
schimbare, dar cred că verificarea este inutilă.
return Object.prototype.toString.call(o) === Object.prototype.toString.call([]);
- person Grant Lindsay; 24.06.2014
Când am postat această întrebare, versiunea de JQuery pe care o foloseam nu includea o funcție isArray
. Dacă ar fi avut, probabil că l-aș fi folosit doar având încredere că implementarea respectivă este cea mai bună modalitate independentă de browser de a efectua această verificare specială a tipului.
Deoarece JQuery oferă acum această funcție, aș folosi-o întotdeauna...
$.isArray(obj);
(începând cu versiunea 1.6.2) Este încă implementat folosind comparații pe șiruri în formă
toString.call(obj) === "[object Array]"
M-am gândit să adaug o altă opțiune pentru cei care ar putea folosi deja biblioteca Underscore.js în scriptul lor. Underscore.js are o funcție isArray() (consultați http://underscorejs.org/#isArray).
_.isArray(object)
Returnează adevărat dacă obiectul este un Array.
Am creat un JSFiddle pentru a crea o cronologie orizontală cu CSS și JQuery. Comportamentul cronologiei este, după cum urmează:
Când pagina se încarcă, „timelineSlider” se poziționează întotdeauna sub „Link 1”. Făcând clic pe fiecare element din listă numit „Link”, „TimelineSlider” alunecă spre și sub acel element din listă.
În prezent, funcționează secvenţial atunci când un utilizator face clic pe Link1, Link2, Link3 și apoi Link4. Dar aș dori ca utilizatorul să facă clic pe orice element din listă în orice ordine, iar „timelineSlider” ar trebui fie să alunece la dreapta sau la stânga, fie să nu schimbe poziția, în funcție de poziția anterioară a „timelineSlider”. Cum îmi pot schimba codul JS pentru a face acest lucru?
$(document).ready(function() {
$("li").click(function() {
//Get Initial timelineSlider Margin
var timelineSliderMargin = parseInt($('.timelineSlider').css('margin-left'));
//Slide the box to the link clicked (left or right) depending on box position
$(".timelineSlider").animate({
'margin-left': (parseInt(calculate(0)) + parseInt($('.timelineSlider').css('margin-left'))) + 'px'
});
});
});
function calculate(i) {
var sum = 0;
for (var j = 0; j <= i; j++) {
sum = sum + $("ul li:eq(" + j + ")").outerWidth(true);
}
return sum;
}
div.eventsWrapper {
height: 75px;
margin-left: 5px;
position: absolute;
width: 800px;
}
.eventsConnector {
background: #0070c0 none repeat scroll 50% 50%;
height: 3px;
left: 0;
margin-left: 185px;
margin-top: -31px;
position: absolute;
transition: transform 0.4s ease 0s;
width: 512px;
z-index: -1;
}
#events {
z-index: 2;
}
#events ul {
list-style-type: none;
padding: 0;
margin: 0;
}
#events li {
display: inline-block;
}
#events a {
display: block;
width: 50px;
height: 50px;
border-radius: 50%;
border: 5px #0070c0 solid;
text-transform: uppercase;
text-decoration: none;
font-size: 15px;
text-align: center;
line-height: 50px;
margin-left: 125px;
z-index: 3;
color: #666666;
background-color: #0070c0;
}
#events a .event {
background-color: #ffffff;
border: 1px solid #ffffff;
border-radius: 50%;
color: #666666;
display: block;
font-size: 15px;
height: 48px;
margin-left: 0;
margin-top: 0;
position: relative;
text-align: center;
text-decoration: none;
text-transform: uppercase;
width: 48px;
z-index: 4;
}
.timelineSlider {
width: 110px;
height: 66px;
border: 0px;
margin-left: 95px;
margin-top: 10px;
position: absolute;
z-index: 2;
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<div class="eventsWrapper">
<div id="events">
<ul>
<li>
<a href="/ro#1">
<div class="event">LINK1</div>
</a>
</li>
<li>
<a href="/ro#2">
<div class="event">LINK2</div>
</a>
</li>
<li>
<a href="/ro#3">
<div class="event">LINK3</div>
</a>
</li>
<li>
<a href="/ro#4">
<div class="event">LINK4</div>
</a>
</li>
</ul>
</div>
<div class="eventsConnector"></div>
<div class="timelineSlider">Slide this box to the link clicked.</div>
</div>
Dacă utilizați Angular, puteți utiliza funcția 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
În JavaScript The Good Parts al lui Crockford, există o funcție pentru a verifica dacă argumentul dat este o matrice:
var is_array = function (value) {
return value &&
typeof value === 'object' &&
typeof value.length === 'number' &&
typeof value.splice === 'function' &&
!(value.propertyIsEnumerable('length'));
};
El explica:
În primul rând, întrebăm dacă valoarea este adevărată. Facem acest lucru pentru a respinge valorile nule și alte valori false. În al doilea rând, întrebăm dacă tipul de valoare este „obiect”. Acest lucru va fi valabil pentru obiecte, matrice și (în mod ciudat) nul. În al treilea rând, întrebăm dacă valoarea are o proprietate de lungime care este un număr. Acest lucru va fi întotdeauna valabil pentru matrice, dar de obicei nu pentru obiecte. În al patrulea rând, întrebăm dacă valoarea conține o metodă de îmbinare. Acest lucru va fi valabil din nou pentru toate matricele. În cele din urmă, întrebăm dacă proprietatea lungime este enumerabilă (lungimea va fi produsă de o buclă for in?). Acest lucru va fi fals pentru toate tablourile. Acesta este cel mai fiabil test pentru matrice pe care l-am găsit. Este regretabil că este atât de complicat.
Soluția universală este mai jos:
Object.prototype.toString.call(obj)=='[object Array]'
Pornind de la ECMAScript 5, o soluție formală este:
Array.isArray(arr)
De asemenea, pentru vechile biblioteci JavaScript, puteți găsi soluția de mai jos, deși nu este suficient de precisă:
var is_array = function (value) {
return value &&
typeof value === 'object' &&
typeof value.length === 'number' &&
typeof value.splice === 'function' &&
!(value.propertyIsEnumerable('length'));
};
Soluțiile sunt de la http://www.pixelstech.net/topic/85-How-to-check-whether-an-object-is-an-array-or-not-in-JavaScript
cod referit de la 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
, cât și unshift
, nu ar fi suficient pentru a testa unshift
?
- person Marco Demaio; 18.02.2014
concat
sau unshift
, dar este mai puțin probabil să aibă ambele.
- person Kris; 24.04.2014
Am folosit această linie de cod:
if (variable.push) {
// variable is array, since AMAIK only arrays have push() method.
}
push
care este adevărată va fi considerat un Array.
- person teleclimber; 28.04.2014
Pentru cei care codifică golf, un test nesigur cu cele mai puține caractere:
function isArray(a) {
return a.map;
}
Acesta este folosit în mod obișnuit atunci când parcurgeți/aplatizați o ierarhie:
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]
De la w3schools:
function isArray(myArray) {
return myArray.constructor.toString().indexOf("Array") > -1;
}
Mi-a plăcut răspunsul lui Brian:
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;
}
}
dar ai putea sa faci asa:
return Object.prototype.toString.call(o) === Object.prototype.toString.call([]);
Am creat acest mic cod, care poate returna tipuri adevărate.
Nu sunt încă sigur de performanță, dar este o încercare de a identifica corect tipul.
https://github.com/valtido/better-typeOf a scris un blog despre asta aici http://www.jqui.net/jquery/better-typeof-than-the-javascript-native-typeof/
funcționează, similar cu tipul actual de.
var user = [1,2,3]
typeOf(user); //[object Array]
Cred că ar putea avea nevoie de un pic de reglare fină și țin cont de lucruri, nu l-am întâlnit sau nu l-am testat corespunzător. deci sunt binevenite îmbunătățiri suplimentare, fie că este vorba de performanță, fie de raportarea incorectă a typeOf.
Cred că folosirea myObj.constructor==Object și myArray.constructor==Matrice este cea mai bună modalitate. Este de aproape 20 de ori mai rapid decât folosirea toString(). Dacă extindeți obiecte cu propriii dvs. constructori și doriți ca acele creații să fie considerate și „obiecte”, atunci acest lucru nu funcționează, dar în rest este mult mai rapid. typeof este la fel de rapid ca metoda constructorului, dar typeof []=='object' returnează adevărat, ceea ce va fi adesea nedorit. http://jsperf.com/constructor-vs-tostring
un lucru de reținut este că null.constructor va arunca o eroare, așa că, dacă s-ar putea să verificați valori nule, va trebui să faceți mai întâi if(testThing!==null){}
Deoarece proprietatea .length este specială pentru matrice în javascript, puteți spune pur și simplu
obj.length === +obj.length // true if obj is an array
Underscorejs și alte câteva biblioteci folosesc acest truc scurt și simplu.
Ceva cu care tocmai am venit:
if (item.length)
//This is an array
else
//not an array
if ('push' in variable.__proto__)
, cel mai rapid și poate cel mai bun mod de a verifica dacă unele var sunt matrice. - person thednp   schedule 06.07.2015