objetos - javascript indexof array of objects
¿Cómo verifica si una variable es una matriz en JavaScript? (23)
Algo que se me ocurrió:
if (item.length) //This is an array else //not an array
Esta pregunta ya tiene una respuesta aquí:
- Comprobar si el objeto es una matriz? 41 respuestas
Me gustaría comprobar si una variable es una matriz o un valor único en JavaScript.
He encontrado una posible solución ...
if (variable.constructor == Array)...
¿Es esta la mejor manera de hacer esto?
Creo que usar myObj.constructor == Object y myArray.constructor == Array es la mejor manera. Es casi 20 veces más rápido que usar toString (). Si extiendes objetos con tus propios constructores y quieres que esas creaciones se consideren "objetos" también, esto no funciona, pero por lo demás es más rápido. typeof es tan rápido como el método constructor, pero typeof [] == ''object'' devuelve true, lo que a menudo será indeseable. http://jsperf.com/constructor-vs-tostring
una cosa a tener en cuenta es que null.constructor generará un error, por lo que si está comprobando los valores nulos, primero deberá hacerlo si (testThing! == null) {}
Cuando publiqué esta pregunta, la versión de JQuery que estaba usando no incluía una función isArray
. Si lo hubiera hecho, probablemente lo habría utilizado confiando en que la implementación sería la mejor forma independiente del navegador para realizar este tipo de verificación en particular.
Dado que JQuery ahora ofrece esta función, siempre la usaría ...
$.isArray(obj);
(a partir de la versión 1.6.2) Todavía se implementa utilizando comparaciones en cadenas en el formulario
toString.call(obj) === "[object Array]"
Desde w3schools :
function isArray(myArray) {
return myArray.constructor.toString().indexOf("Array") > -1;
}
En JavaScript Las partes buenas de Crockford, hay una función para verificar si el argumento dado es una matriz:
var is_array = function (value) {
return value &&
typeof value === ''object'' &&
typeof value.length === ''number'' &&
typeof value.splice === ''function'' &&
!(value.propertyIsEnumerable(''length''));
};
El explica:
Primero, preguntamos si el valor es veraz. Hacemos esto para rechazar valores nulos y otros falsos. En segundo lugar, preguntamos si el valor de typeof es ''objeto''. Esto será cierto para los objetos, matrices y (extrañamente) nulo. Tercero, preguntamos si el valor tiene una propiedad de longitud que es un número. Esto siempre será cierto para los arreglos, pero generalmente no para los objetos. Cuarto, preguntamos si el valor contiene un método de empalme. Esto volverá a ser verdad para todas las matrices. Finalmente, preguntamos si la propiedad de longitud es enumerable (¿la longitud será producida por un bucle for en?). Eso será falso para todas las matrices. Esta es la prueba más confiable para la variedad que he encontrado. Es lamentable que sea tan complicado.
En los navegadores modernos (y algunos navegadores heredados), puede hacer
Array.isArray(obj)
( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray Chrome 5, Firefox 4.0, IE 9, Opera 10.5 y Safari 5)
Si necesita admitir versiones anteriores de IE, puede usar es5-shim para polyfill Array.isArray; o agregue lo siguiente
# 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]'';
}
};
Si usa jQuery, puede usar jQuery.isArray(obj)
o $.isArray(obj)
. Si usa el guión bajo, puede usar _.isArray(obj)
Si no necesita detectar matrices creadas en diferentes marcos, también puede usar instanceof
obj instanceof Array
Nota : la palabra clave de arguments
que se puede usar para acceder al argumento de una función no es una matriz, aunque (generalmente) se comporta como una:
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)
Esta es una pregunta antigua, pero teniendo el mismo problema, encontré una solución muy elegante que quiero compartir.
Agregar un prototipo a Array lo hace muy simple
Array.prototype.isArray = true;
Ahora, una vez, si tiene un objeto que desea probar para ver si es una matriz, todo lo que necesita es verificar la nueva propiedad.
var box = doSomething();
if (box.isArray) {
// do something
}
isArray solo está disponible si es una matriz
Estaba usando esta línea de código:
if (variable.push) {
// variable is array, since AMAIK only arrays have push() method.
}
Hay múltiples soluciones con todas sus peculiaridades. Esta página da una buena visión general. Una posible solución es:
function isArray(o) {
return Object.prototype.toString.call(o) === ''[object Array]'';
}
Hay varias formas de verificar si una variable es una matriz o no. La mejor solución es la que has elegido.
variable.constructor === Array
Este es el método más rápido en Chrome, y muy probablemente en todos los otros navegadores. Todas las matrices son objetos, por lo que comprobar la propiedad del constructor es un proceso rápido para los motores de JavaScript.
Si tiene problemas para averiguar si una propiedad de objetos es una matriz, primero debe verificar si la propiedad está allí.
variable.prop && variable.prop.constructor === Array
Algunas otras formas son:
variable instanceof Array
Este método ejecuta aproximadamente 1/3 de la velocidad como el primer ejemplo. Aún bastante sólido, se ve más limpio, si te gusta el código bonito y no tanto el rendimiento. Tenga en cuenta que la comprobación de números no funciona como variable instanceof Number
siempre devuelve false
. Actualización: ¡ instanceof
ahora va 2/3 de la velocidad!
Array.isArray(variable)
Este último es, en mi opinión, el más feo, y es uno de los más lentos. Ejecutando alrededor de 1/5 de la velocidad como el primer ejemplo. Array.prototype, es en realidad una matriz. Puede leer más sobre esto aquí https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
Así que otra actualización más
Object.prototype.toString.call(variable) === ''[object Array]'';
Este tipo es el más lento para tratar de buscar una matriz. Sin embargo, esta es una ventanilla única para cualquier tipo que estés buscando. Sin embargo, ya que estás buscando una matriz, solo usa el método más rápido de arriba.
Además, hice algunas pruebas: http://jsperf.com/instanceof-array-vs-array-isarray/33 Así que diviértete y échale un vistazo.
Nota: @EscapeNetscape ha creado otra prueba porque jsperf.com está inactivo. http://jsben.ch/#/QgYAV Quería asegurarme de que el enlace original permanezca para cuando jsperf vuelva a estar en línea.
He creado este pequeño código, que puede devolver tipos verdaderos.
Todavía no estoy seguro del rendimiento, pero es un intento de identificar correctamente el tipo.
https://github.com/valtido/better-typeOf también publicó un poco sobre esto aquí http://www.jqui.net/jquery/better-typeof-than-the-javascript-native-typeof/
Funciona, similar al tipo actual.
var user = [1,2,3]
typeOf(user); //[object Array]
Piensa que puede necesitar un poco de ajuste fino y, teniendo en cuenta las cosas, no lo he encontrado o no lo he probado correctamente. por lo tanto, las mejoras adicionales son bienvenidas, ya sea en lo que respecta al rendimiento, o la devolución incorrecta de typeOf.
La solución universal está abajo:
Object.prototype.toString.call(obj)==''[object Array]''
A partir de ECMAScript 5, una solución formal es:
Array.isArray(arr)
Además, para las librerías de JavaScript antiguas, puedes encontrar la siguiente solución aunque no es lo suficientemente precisa:
var is_array = function (value) {
return value &&
typeof value === ''object'' &&
typeof value.length === ''number'' &&
typeof value.splice === ''function'' &&
!(value.propertyIsEnumerable(''length''));
};
Las soluciones son de http://www.pixelstech.net/topic/85-How-to-check-whether-an-object-is-an-array-or-not-in-JavaScript
Me gustó la respuesta de 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;
}
}
pero podrías hacer así:
return Object.prototype.toString.call(o) === Object.prototype.toString.call([]);
Noté que alguien mencionó jQuery, pero no sabía que existía una función isArray()
. Resulta que fue agregado en la versión 1.3.
jQuery lo implementa como Peter sugiere:
isArray: function( obj ) {
return toString.call(obj) === "[object Array]";
},
Después de confiar mucho en jQuery (especialmente sus técnicas de compatibilidad entre navegadores) actualizaré a la versión 1.3 y usaré su función (siempre que la actualización no cause demasiados problemas) o usaré este método sugerido directamente en mi código.
Muchas gracias por las sugerencias.
Para aquellos que codifican el golf, una prueba poco confiable con menos caracteres:
function isArray(a) {
return a.map;
}
Esto se usa comúnmente al atravesar / aplanar una jerarquía:
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]
Pensé que agregaría otra opción para aquellos que ya estarían usando la biblioteca Underscore.js en su script. Underscore.js tiene una función isArray () (consulte http://underscorejs.org/#isArray ).
_.isArray(object)
Devuelve true si el objeto es un Array.
Personalmente, me gusta la sugerencia de Peter: https://.com/a/767499/414784 (para ECMAScript 3. Para ECMAScript 5, use Array.isArray()
)
Los comentarios en la publicación indican, sin embargo, que si se cambia toString()
, la forma de verificar una matriz fallará. Si realmente quieres ser específico y asegurarte de que toString()
no haya cambiado, y no hay problemas con el atributo de clase de objetos ( [object Array]
es el atributo de clase de un objeto que es una matriz), entonces recomiendo hacerlo algo como esto:
//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;
}
}
Tenga en cuenta que en la 6ª edición de la Guía definitiva de JavaScript, 7.10, dice que Array.isArray()
se implementa utilizando Object.prototype.toString.call()
en ECMAScript 5. También tenga en cuenta que si va a preocuparse por toString()
'' Si la implementación cambia, también debe preocuparse por cualquier otro método integrado que cambie también. ¿Por qué usar push()
? ¡Alguien puede cambiarlo! Tal enfoque es tonto. La verificación anterior es una solución ofrecida a aquellos preocupados por el cambio de la toString()
, pero creo que la verificación es innecesaria.
Si está utilizando Angular, puede usar la función angular.isArray ()
var myArray = [];
angular.isArray(myArray); // returns true
var myObj = {};
angular.isArray(myObj); //returns false
Si solo está trabajando con EcmaScript 5 y superior, puede usar la función Array.isArray
incorporada
p.ej,
Array.isArray([]) // true
Array.isArray("foo") // false
Array.isArray({}) // false
También podrías usar:
if (value instanceof Array) {
alert(''value is Array!'');
} else {
alert(''Not an array'');
}
Esto me parece una solución bastante elegante, pero a cada uno lo suyo.
Editar:
A partir de ES5 ahora hay también:
Array.isArray(value);
Pero esto se romperá en los navegadores más antiguos, a menos que esté utilizando polyfills (básicamente ... IE8 o similar).
Via Crockford :
function typeOf(value) {
var s = typeof value;
if (s === ''object'') {
if (value) {
if (value instanceof Array) {
s = ''array'';
}
} else {
s = ''null'';
}
}
return s;
}
La falla principal que menciona Crockford es la incapacidad de determinar correctamente las matrices que se crearon en un contexto diferente, por ejemplo, una window
. Esa página tiene una versión mucho más sofisticada si esto no es suficiente.
Ya que la propiedad .length es especial para arreglos en javascript, simplemente puede decir
obj.length === +obj.length // true if obj is an array
Underscorejs y varias otras bibliotecas utilizan este truco corto y simple.
código referido desde 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);};