viernes, 7 de junio de 2013

Detectar si una variable es un array en JavaScript

Para detectar el tipo de una variable normalmente utilizamos el operador typeof:

typeof "Hello";  //returns "string"
typeof 3;  //returns "number"

Este operador funciona bien para los tipos boolean, number, string y undefined, pero cuando la variable es un objeto ( por ejemplo un Array ) devuelve siempre "object":


typeof [];  //returns "object"
typeof {};  //returns "object"
typeof new Date(); //returns "object" 

El operador instanceof

Para conocer el tipo de objeto utilizamos el operador instanceof de la siguiente forma:

variable instanceof constructor;

De esta forma podemos preguntar si una variable es una instancia de Array, de Date, de algún constructor propio, etc.


var myArray = [];

myArray instanceof Array;  // true
myArray instanceof Number; // false
myArray instanceof String; // false
myArray instanceof Object; // true

En la última línea vemos que para un array, el operador también devuelve true en la comparación con Object. Esto es porque un array es una instancia de 'Array' y tambien de 'Object' porque el constructor Array hereda de Object.

Problemas si utilizamos multiples frames

La solución que hemos visto nos dará problemas si manejamos arrays creados en frames diferentes. Cada frame en una página tiene un entorno DOM propio y cada uno tendrá su propia clase 'Array' y 'Object'. Si intentamos hacer la comprobación con un array creado en otro frame:


arrayFromAnotherFrame instanceof Array;  // false

El resultado es false porque no es una instancia del constructor 'Array' de este frame.

El estándar de facto para detectarlo correctamente en todos los casos, propuesto por Juriy Zaytsev (Kangax), consiste en utilizar toString sobre el objeto y comprobar si devuelve "[object Array]":


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

ECMAScript 5 introduce Array.isArray()

La nueva versión de JavaScript introduce un método específico para detectar si un valor es un array:


var myArray = [];

Array.isArray( myArray );  // true

Soportado en IE9+, Firefox 4+, Chrome, Safari 5+ and Opera 10.5+.

Una buena solución si tenemos que dar soporte a navegadores antiguos es crear el método isArray si no existe:

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

Fuentes:
Perfection Kills: instanceof considered harmful

No hay comentarios:

Publicar un comentario