¿Hay una mejor manera de obtener el tipo de variable en JS que typeof? Funciona bien cuando haces:

> typeof 1
"number"
> typeof "hello"
"string"

Pero es inútil cuando intentas:

> typeof [1,2]
"object"
>r = new RegExp(/./)
/./
> typeof r
"function"

Sé de instanceof, pero esto requiere que sepas el tipo de antemano.

> [1,2] instanceof Array
true
> r instanceof RegExp
true

¿Hay una mejor manera?

274
Aillyn 12 sep. 2011 a las 19:39

11 respuestas

La mejor respuesta

Angus Croll escribió recientemente una publicación de blog interesante sobre esto:

http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/

Revisa los pros y los contras de los diversos métodos y luego define un nuevo método 'toType':

var toType = function(obj) {
  return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}
218
ipr101 12 sep. 2011 a las 15:53

También podemos cambiar un pequeño ejemplo de ipr101

Object.prototype.toType = function() {
  return ({}).toString.call(this).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}

Y llama como

"aaa".toType(); // 'string'
15
greymaster 8 nov. 2012 a las 13:52

Puede encontrar útil la siguiente función:

function typeOf(obj) {
  return {}.toString.call(obj).split(' ')[1].slice(0, -1).toLowerCase();
}

O en ES7 (comenta si hay más mejoras)

function typeOf(obj) {
  const { toString } = Object.prototype;
  const stringified = obj::toString();
  const type = stringified.split(' ')[1].slice(0, -1);

  return type.toLowerCase();
}

Resultados:

typeOf(); //undefined
typeOf(null); //null
typeOf(NaN); //number
typeOf(5); //number
typeOf({}); //object
typeOf([]); //array
typeOf(''); //string
typeOf(function () {}); //function
typeOf(/a/) //regexp
typeOf(new Date()) //date
typeOf(new Error) //error
typeOf(Promise.resolve()) //promise
typeOf(function *() {}) //generatorfunction
typeOf(new WeakMap()) //weakmap
typeOf(new Map()) //map

Gracias @johnrees por notificarme de: error, promesa, función del generador

31
Vix 15 ago. 2018 a las 01:48

Puedes intentar usar constructor.name.

[].constructor.name
new RegExp().constructor.name

Al igual que con todo JavaScript, alguien eventualmente señalará invariablemente que esto es de alguna manera malvado, así que aquí hay un enlace a una respuesta que cubre esto bastante bien.

Una alternativa es usar Object.prototype.toString.call

Object.prototype.toString.call([])
Object.prototype.toString.call(/./)
49
Community 23 may. 2017 a las 12:26

¡Mis 2 ¢! Realmente, parte de la razón por la que estoy lanzando esto aquí, a pesar de la larga lista de respuestas, es para proporcionar un poco más de all in one escriba la solución y obtenga información en el futuro sobre cómo expandirla para incluir más real types .

Con la siguiente solución, como se mencionó anteriormente, combiné un par de soluciones encontradas aquí, así como también incorporé una corrección para devolver un valor de jQuery en el objeto definido jQuery si está disponible . También agrego el método al prototipo de objeto nativo. Sé que a menudo es tabú, ya que podría interferir con otras extensiones, pero lo dejo a user beware . Si no le gusta esta forma de hacerlo, simplemente copie la función base en cualquier lugar que desee y reemplace todas las variables de this con un parámetro de argumento para pasar (como los argumentos [0]).

;(function() {  //  Object.realType
    function realType(toLower) {
        var r = typeof this;
        try {
            if (window.hasOwnProperty('jQuery') && this.constructor && this.constructor == jQuery) r = 'jQuery';
            else r = this.constructor && this.constructor.name ? this.constructor.name : Object.prototype.toString.call(this).slice(8, -1);
        }
        catch(e) { if (this['toString']) r = this.toString().slice(8, -1); }
        return !toLower ? r : r.toLowerCase();
    }
    Object['defineProperty'] && !Object.prototype.hasOwnProperty('realType')
        ? Object.defineProperty(Object.prototype, 'realType', { value: realType }) : Object.prototype['realType'] = realType;
})();

Luego, simplemente use con facilidad, así:

obj.realType()  //  would return 'Object'
obj.realType(true)  //  would return 'object'

Nota: hay 1 argumento aceptable. Si es bool de true, la devolución siempre estará en minúsculas .

Más ejemplos:

true.realType();                            //  "Boolean"
var a = 4; a.realType();                    //  "Number"
$('div:first').realType();                   // "jQuery"
document.createElement('div').realType()    //  "HTMLDivElement"

Si tiene algo que agregar que pueda ser útil, como definir cuándo se creó un objeto con otra biblioteca (Moo, Proto, Yui, Dojo, etc.), siéntase libre de comentar o editar esto y mantenerlo como más exacto y preciso. O pase al GitHub lo hice y Házmelo saber. También encontrará un enlace rápido a un archivo cdn min allí.

3
SpYk3HH 9 jul. 2016 a las 16:38

Función de una línea:

function type(obj) {
    return Object.prototype.toString.call(obj).replace(/^\[object (.+)\]$/,"$1").toLowerCase()
}

Esto da el mismo resultado que jQuery.type()

9
Yukulélé 1 may. 2017 a las 11:50
function getType(obj) {
    if(obj && obj.constructor && obj.constructor.name) {
        return obj.constructor.name;
    }
    return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
}

En mis pruebas preliminares, esto funciona bastante bien. El primer caso imprimirá el nombre de cualquier objeto creado con "nuevo", y el segundo caso debería capturar todo lo demás.

Estoy usando (8, -1) porque supongo que el resultado siempre comenzará con [object y terminará con ], pero no estoy seguro de que eso sea cierto en todos los escenarios.

2
mpen 6 jun. 2016 a las 16:10

Supongo que la solución más universal aquí es verificar primero undefined y null, luego simplemente llamar a constructor.name.toLowerCase().

const getType = v =>
  v === undefined
    ? 'undefined'
    : v === null
      ? 'null'
      : v.constructor.name.toLowerCase();




console.log(getType(undefined)); // 'undefined'
console.log(getType(null)); // 'null'
console.log(getType('')); // 'string'
console.log(getType([])); // 'array'
console.log(getType({})); // 'object'
console.log(getType(new Set())); // `set'
console.log(getType(Promise.resolve())); // `promise'
console.log(getType(new Map())); // `map'
0
Arsenowitch 26 nov. 2019 a las 16:02

La condición typeof se usa para verificar el tipo de variable, si se verifica el tipo de variable en la condición if-else p.ej.

if(typeof Varaible_Name "undefined")
{

}
0
Shree 26 feb. 2020 a las 09:19

Puede aplicar Object.prototype.toString a cualquier objeto:

var toString = Object.prototype.toString;

console.log(toString.call([]));
//-> [object Array]

console.log(toString.call(/reg/g));
//-> [object RegExp]

console.log(toString.call({}));
//-> [object Object]

Esto funciona bien en todos los navegadores, con la excepción de IE: al llamar a esto en una variable obtenida de otra ventana, simplemente escupirá [object Object].

3
Andy E 12 sep. 2011 a las 15:46

Una función de captura de tipo razonablemente buena es la utilizada por YUI3:

var TYPES = {
    'undefined'        : 'undefined',
    'number'           : 'number',
    'boolean'          : 'boolean',
    'string'           : 'string',
    '[object Function]': 'function',
    '[object RegExp]'  : 'regexp',
    '[object Array]'   : 'array',
    '[object Date]'    : 'date',
    '[object Error]'   : 'error'
},
TOSTRING = Object.prototype.toString;

function type(o) {
    return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null');
};

Esto captura muchas de las primitivas proporcionadas por javascript, pero siempre puede agregar más modificando el objeto TYPES. Tenga en cuenta que typeof HTMLElementCollection en Safari informará function, pero el tipo (HTMLElementCollection) devolverá object

38
Nick Husher 12 sep. 2011 a las 15:49