Compruebe si un valor es un objeto en JavaScript


1365

¿Cómo se verifica si un valor es un Objeto en JavaScript?


44
Una variable es una variable. Puede referirse a un objeto. Además, es posible que desee definir "objeto": como muestran las respuestas y los comentarios, hay varias definiciones en conflicto (por ejemplo, si nulles un objeto).

8
OP, IMO, debe aceptar la respuesta de @ Daan, ya que es la mejor solución y debe enumerarse sobre otras respuestas para que se vea primero. (Sin ofender a otros que también tienen buenas respuestas.)
tiffon

2
En mi humilde opinión, realmente depende de lo que usted (el que busca una respuesta a esta pregunta) considere un Objeto y por qué lo está verificando. Esta pregunta ofrece diferentes respuestas si está intentando distinguir matrices (que son objetos) de otros objetos o si está tratando de separar los valores escalares de los "vectores". Y si se debe excluir o no nulo (que es un Objeto, de acuerdo con typeof) o Funciones (que son Objetos), realmente depende de por qué lo esté verificando. Es por eso que hay tantas respuestas y la mayoría de ellas, en contexto, son correctas.
FrancescoMM

const isEmpty = thing => {typeof thing === "objeto"? ! cosa || ! Object.keys (thing) .length:! Thing && thing! == 0};
Mayur S

1
Sería genial si pudieras comenzar diciendo exactamente qué quieres decir con "es un objeto". (O, diga explícitamente que parte de la respuesta que busca es concretar varios significados populares de "es un objeto" y luego diferenciarlos). A falta de eso, todos están hablando unos de otros.
Don Hatch

Respuestas:


520

ACTUALIZACIÓN :

Esta respuesta es incompleta y da resultados engañosos . Por ejemplo,null también se considera de tipo objectJavaScript, sin mencionar otros casos extremos. Siga la recomendación a continuación y continúe con la otra "respuesta más votada (¡y correcta!)" .


Respuesta original :

Intenta usar typeof(var)y / o var instanceof something.

EDIT: Esta respuesta da una idea de cómo examinar las propiedades de variables, pero es no una receta a prueba de balas (después de todo, no existe una receta en absoluto!) Para comprobar si se trata de un objeto, ni mucho menos. Dado que las personas tienden a buscar algo para copiar desde aquí sin hacer ninguna investigación, recomiendo encarecidamente que recurran a la otra respuesta más votada (¡y correcta!).


208
typeofes un operador, por lo que no es necesario ().
Yoshi

67
Si, no hace falta. Solo lo prefiero de esta manera.
Michael Krelin - hacker

150
@ MichaelKrelin-hacker: Eso es lamentable ya que confunde a las personas .
RightSaidFred

11
@RightSaidFred, no tengo ninguna explicación, pero no estoy dispuesto a agregar corchetes adicionales en estas expresiones :)
Michael Krelin - hacker

117
Esta respuesta es incorrecta. typeofdevuelve 'objeto' para nulo, que no es un objeto, y instanceofno funciona para objetos creados usando Object.create(null).
Nikolai

1636

Si typeof yourVariable === 'object', es un objeto o nulo. Si desea excluir nulo, simplemente hágalo typeof yourVariable === 'object' && yourVariable !== null.


31
Las funciones también son objetos y deben incluirse en su cheque.
JS_Riddler

44
En este caso sería yourVariable !== nullmejor práctica?
hippietrail

99
@RightSaidFred Parece que typeof null == 'object'no se solucionará en ES6 . Ellos dijeron:This proposal has been rejected. It was implemented in V8 but it turned out that it broke a lot of existing sites. In the spirit of One JavaScript this is not feasible.
Konstantin Smolyanin

2
@Orion la respuesta simple es que las matrices se consideran objetos. Para obtener una respuesta más detallada, tendrá que seguir leyendo typeofporque tiene algunos casos especiales que no necesariamente tienen mucho sentido. Si está tratando de diferenciar entre matrices y objetos que no son matrices, entonces definitivamente no desea usar typeof.
Matt Fenwick

8
@Tresdin La mejor manera es correr Object.prototype.toString.call(yourVar), siendo yourVar lo que necesita inspeccionar. En caso de matrices, Object.prototype.toString.call([1,2])regresa[object Array]
Jose Rui Santos

539

Definamos "objeto" en Javascript . Según los documentos de MDN , cada valor es un objeto o una primitiva:

primitivo, valor primitivo

Un dato que no es un objeto y no tiene ningún método. JavaScript tiene 5 tipos de datos primitivos: cadena, número, booleano, nulo, indefinido.

¿Qué es un primitivo?

  • 3
  • 'abc'
  • true
  • null
  • undefined

¿Qué es un objeto (es decir, no un primitivo)?

  • Object.prototype
  • todo descendió de Object.prototype
    • Function.prototype
      • Object
      • Function
      • function C(){} - funciones definidas por el usuario
    • C.prototype- la propiedad prototipo de una función definida por el usuario: esto no es C es el prototipo s
      • new C() - "nuevo" -ing una función definida por el usuario
    • Math
    • Array.prototype
      • matrices
    • {"a": 1, "b": 2} - objetos creados usando notación literal
    • new Number(3) - envoltorios alrededor de primitivas
    • ... muchas otras cosas ...
  • Object.create(null)
  • todo descendió de un Object.create(null)

Cómo verificar si un valor es un objeto

instanceof por sí solo no funcionará, ya que se pierden dos casos:

// oops:  isObject(Object.prototype) -> false
// oops:  isObject(Object.create(null)) -> false
function isObject(val) {
    return val instanceof Object; 
}

typeof x === 'object'no funcionará debido a falsos positivos ( null) y falsos negativos (funciones):

// oops: isObject(Object) -> false
function isObject(val) {
    return (typeof val === 'object');
}

Object.prototype.toString.call no funcionará, debido a falsos positivos para todas las primitivas:

> Object.prototype.toString.call(3)
"[object Number]"

> Object.prototype.toString.call(new Number(3))
"[object Number]"

Entonces uso:

function isObject(val) {
    if (val === null) { return false;}
    return ( (typeof val === 'function') || (typeof val === 'object') );
}

La respuesta de @ Daan también parece funcionar:

function isObject(obj) {
  return obj === Object(obj);
}

porque, según los documentos de MDN :

El constructor de objetos crea un contenedor de objetos para el valor dado. Si el valor es nulo o indefinido, creará y devolverá un objeto vacío; de lo contrario, devolverá un objeto de un tipo que corresponde al valor dado. Si el valor ya es un objeto, devolverá el valor.


Una tercera forma que parece funcionar (no estoy seguro si es 100%) es usar Object.getPrototypeOfque arroje una excepción si su argumento no es un objeto:

// these 5 examples throw exceptions
Object.getPrototypeOf(null)
Object.getPrototypeOf(undefined)
Object.getPrototypeOf(3)
Object.getPrototypeOf('abc')
Object.getPrototypeOf(true)

// these 5 examples don't throw exceptions
Object.getPrototypeOf(Object)
Object.getPrototypeOf(Object.prototype)
Object.getPrototypeOf(Object.create(null))
Object.getPrototypeOf([])
Object.getPrototypeOf({})

22
obj === Object(obj)devuelve truepara matrices.
Onur Yıldırım

55
var x = []; console.log(x === Object(x)); // return true
Iluminador

66
Las matrices @Illuminator son objetos en Javascript, como mencioné en mi respuesta.
Matt Fenwick

1
getPrototypeOfno funciona, por ejemplo, con proxys revocados, que son objetos pero arrojan.
Oriol

2
¿Por qué no ({}).toString.apply(obj) === '[object Object]'esto distingue entre matrices y objetos que no son matrices?
MauricioJuanes

295

underscore.js proporciona el siguiente método para averiguar si algo es realmente un objeto:

_.isObject = function(obj) {
  return obj === Object(obj);
};

ACTUALIZAR

Debido a un error anterior en V8 y una pequeña optimización de micro velocidad, el método tiene el siguiente aspecto desde underscore.js 1.7.0 (agosto de 2014):

_.isObject = function(obj) {
  var type = typeof obj;
  return type === 'function' || type === 'object' && !!obj;
};

57
En javascript, una matriz también es un objeto, por lo que la mayoría de las veces desea excluir la matriz:return obj === Object(obj) && Object.prototype.toString.call(obj) !== '[object Array]'
Daan

22
¿por qué excluirías una matriz? Son objetos completos.
Nikolai

65
Porque la mayoría de las veces desea distinguir un {} de un [] por ejemplo como entrada en una función
Daan

55
@Nickolai ..y para iterar a través de objetos anidados.
Ricky Boyce

66
Gran respuesta. Manijas nulltambién. Debería ser la respuesta aceptada.
tiffon

180

Object.prototype.toString.call(myVar) volverá:

  • "[object Object]" si myVar es un objeto
  • "[object Array]" si myVar es una matriz
  • etc.

Para obtener más información sobre esto y por qué es una buena alternativa a typeof, consulte este artículo .


12
Hace poco aprendí que typeof [] === 'object'-> true. Eso es lo que necesitas este método.
Jondlm

3
@Christophe No distingue entre primitivas y objetos . Object.prototype.toString.call(3)-> "[object Number]". Object.prototype.toString.call(new Number(3))-> "[object Number]"
Matt Fenwick

3
@MattFenwick No creo que este sea el tipo de "objeto" que el OP está tratando de identificar
Christophe

3
@Christophe, ¿por qué piensas eso? En mi humilde opinión, en ausencia de cualquier otra definición dada por el OP para "objeto", me parece más razonable ir con la que se utiliza de manera coherente en toda la especificación de ECS.
Matt Fenwick

getType=function(obj){return Object.prototype.toString.call(obj).match(/\[object (\w+)\]/)[1];};
Sr. Polywhirl

117

Para verificar simplemente contra Object o Array sin función adicional llamada (velocidad). Como también publicado aquí .

isArray ()

isArray = function(a) {
    return (!!a) && (a.constructor === Array);
};
console.log(isArray(        )); // false
console.log(isArray(    null)); // false
console.log(isArray(    true)); // false
console.log(isArray(       1)); // false
console.log(isArray(   'str')); // false
console.log(isArray(      {})); // false
console.log(isArray(new Date)); // false
console.log(isArray(      [])); // true

isObject () - Nota: use solo para literales de objetos, ya que devuelve falso para objetos personalizados, como nueva fecha o nuevo YourCustomObject.

isObject = function(a) {
    return (!!a) && (a.constructor === Object);
};
console.log(isObject(        )); // false
console.log(isObject(    null)); // false
console.log(isObject(    true)); // false
console.log(isObject(       1)); // false
console.log(isObject(   'str')); // false
console.log(isObject(      [])); // false
console.log(isObject(new Date)); // false
console.log(isObject(      {})); // true

isObjectsolo funciona con literales de objeto. Si creo un tipo personalizado, creo una instancia del tipo y lo false
pruebo

3
@zupa: ¿qué?

44
@ 3000 bien, si omitimos la parte (!! a) se bloquea, porque nulo e indefinido no tienen constructores. (!! a) los filtra. Eso responde tu pregunta?
zupa

2
@zupa @ 3000 Boolean(a)es más largo, pero mucho más intuitivo. Simplemente no use new Boolean(a): ( aquí está el por qué )!
JayVee

10
Sorprendido, la mejor respuesta está tan lejos en la página. Básicamente, esto responde a la pregunta: ¿se representaría en JSON como algo que comience con un {personaje? Para el caso de la matriz, siempre que no necesite admitir IE <9, puede usar Array.isArray()para determinar si algo es una matriz. Pasa todos los casos de prueba que proporcionó.
Kip

81

Me gusta simplemente:

function isObject (item) {
  return (typeof item === "object" && !Array.isArray(item) && item !== null);
}

Si el elemento es un objeto JS, y no es una matriz JS, y no es null... si los tres demuestran ser verdaderos, regrese true. Si alguna de las tres condiciones falla, la &&prueba hará un cortocircuito y falseserá devuelta. La nullprueba se puede omitir si lo desea (dependiendo de cómo usenull ).

DOCS:

http://devdocs.io/javascript/operators/typeof

http://devdocs.io/javascript/global_objects/object

http://devdocs.io/javascript/global_objects/array/isarray

http://devdocs.io/javascript/global_objects/null


3
¿Qué pasa con console.log (isObject (new Date ()))? ¿Por qué una fecha debería ser un objeto pero una matriz no?
schirrmacher

55
@macher Porque new Date()devuelve un objeto. Una matriz es, desde un punto de vista lógico, no un objeto, aunque JavaScript los maneja e informa como tal. Sin embargo, en la práctica, no es útil verlos iguales, porque no lo son. Un objeto no tiene lengthatributo, por ejemplo, y no tiene métodos como push (). Y a veces es posible que desee asignar parámetros a una función sobrecargada, donde debe marcar la diferencia entre una matriz o un objeto, especialmente si otros parámetros dependen de cuál se proporcionó.
StanE

1
Las matrices @StanE son definitivamente objetos. No estoy seguro de por qué cree que los objetos no pueden tener una lengthpropiedad ni métodos como push, Object.create(Array.prototype)es un contraejemplo trivial de un objeto sin matriz que los tiene. Lo que hace que las matrices sean especiales es que son objetos exóticos con un método interno esencial personalizado [[DefineOwnProperty]], pero siguen siendo objetos.
Oriol

44
@ Oriol No escribí que las matrices no son objetos ni escribí que los objetos no pueden tener una lengthpropiedad (quise decir que los literales de objeto no tienen lengthatributo por defecto). Escribí que las matrices no son objetos desde un punto de vista lógico . Estoy hablando de la lógica del programa. A veces es necesario verificar si una matriz es una matriz "real" y definitivamente no es un objeto "real". Para eso Array.isArray()es eso . Imagine que tiene una función que acepta un objeto o una matriz de objetos. Buscar un atributo o método especial es una solución sucia. La forma nativa siempre es mejor.
StanE

2
typeof nulles "object"no "undefined".
2540625

80

Con función Array.isArray:

function isObject(o) {
  return o !== null && typeof o === 'object' && Array.isArray(o) === false;
}

Sin función Array.isArray:

Me sorprendió la cantidad de votos a favor de las respuestas incorrectas 😮 ¡¡¡¡¡
Solo 1 respuesta pasó mis exámenes !!! Aquí he creado mi versión simplificada:

function isObject(o) {
  return o instanceof Object && o.constructor === Object;
}

En cuanto a mí, es claro y simple, ¡y simplemente funciona! Aquí mis pruebas:

console.log(isObject({}));             // Will return: true
console.log(isObject([]));             // Will return: false
console.log(isObject(null));           // Will return: false
console.log(isObject(/.*/));           // Will return: false
console.log(isObject(function () {})); // Will return: false

UNA VEZ MÁS: ¡no todas las respuestas pasan esta prueba! 🙈


En caso de que necesite verificar que el objeto es una instancia de una clase particular, debe verificar el constructor con su clase particular, como:

function isDate(o) {
  return o instanceof Object && o.constructor === Date;
}

prueba simple:

var d = new Date();
console.log(isObject(d)); // Will return: false
console.log(isDate(d));   // Will return: true

Como resultado, tendrá un código estricto y robusto.


En caso de que no va a crear funciones como isDate, isError, isRegExp, etc usted puede considerar la opción de utilizar estas funciones generalizadas:

function isObject(o) {
  return o instanceof Object && typeof o.constructor === 'function';
}

no funcionará correctamente para todos los casos de prueba mencionados anteriormente, pero es lo suficientemente bueno para todos los objetos (simples o construidos).


isObjectno funcionará en caso de Object.create(null)que la implementación interna Object.createse explica aquí, pero puede usarla isObjecten una implementación más sofisticada:

function isObject(o, strict = true) {
  if (o === null || o === undefined) {
    return false;
  }
  const instanceOfObject = o instanceof Object;
  const typeOfObject = typeof o === 'object';
  const constructorUndefined = o.constructor === undefined;
  const constructorObject = o.constructor === Object;
  const typeOfConstructorObject = typeof o.constructor === 'function';
  let r;
  if (strict === true) {
    r = (instanceOfObject || typeOfObject) && (constructorUndefined || constructorObject);
  } else {
    r = (constructorUndefined || typeOfConstructorObject);
  }
  return r;
};

¡Ya hay un paquete creado en npm v1 basado en esta implementación! ¡Y funciona para todos los casos de prueba descritos anteriormente! 🙂


¡la mejor respuesta! funciona para muchos de los casos mencionados aquí
prieston

Como esto devuelve falso para isObject (myDateObject), esta no es una respuesta a la pregunta. No indica si una variable es un objeto, solo si es un objeto de una clase específica. La pregunta aquí es para una función genérica que devuelve verdadero para cualquier objeto.
Yetanotherjosh

@Yetanotherjosh Es una respuesta de hecho 🤓 mencionó el caso que se describe en la respuesta, y el punto: debe usar isDatepara suDateObject con el propósito de escribir código robusto, de lo contrario tendrá quebradizoisObject método .
V. Kovpak

@VladimirKovpak Usar Dateen mi comentario fue mal elegido porque sí, la respuesta sí discute Date. Pero Datees solo una de las infinitas clases posibles y el punto es válido para cualquier otra clase. Ejemplo: class Foo() { }; var x = new Foo(); isObject(x)devoluciones false. No sé exactamente cuál es el caso de uso del OP, pero es fácil concebir escenarios en los que no sea ​​factible tener que conocer todas las clases posibles y verificar específicamente cada una de ellas .
Yetanotherjosh

@Yetanotherjosh He actualizado mi respuesta. Y agregó 1 caso más.
V. Kovpak

41

¡Oh Dios mío! Creo que esto podría ser más corto que nunca, veamos esto:

Código corto y final

function isObject(obj)
{
    return obj != null && obj.constructor.name === "Object"
}

console.log(isObject({})) // returns true
console.log(isObject([])) // returns false
console.log(isObject(null)) // returns false

Explicado

Tipos de retorno

tipo de objetos JavaScript (incluidos null) devuelve"object"

console.log(typeof null, typeof [], typeof {})

Comprobando sus constructores

Comprobar en su constructorpropiedad devuelve la función con sus nombres.

console.log(({}).constructor) // returns a function with name "Object"
console.log(([]).constructor) // returns a function with name "Array"
console.log((null).constructor) //throws an error because null does not actually have a property

Introduciendo Function.name

Function.namedevuelve un nombre de solo lectura de una función o "anonymous"para cierres.

console.log(({}).constructor.name) // returns "Object"
console.log(([]).constructor.name) // returns "Array"
console.log((null).constructor.name) //throws an error because null does not actually have a property

Nota: A partir de 2018, Function.name podría no funcionar en IE https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Browser_compatibility


3
Realmente me gusta este, corto y al grano. Solo falla en 1 cosa hasta donde puedo ver. if obj = Object.create(null)y por qué lo harías de todos modos ...?
Julian Knight

29

OK, vamos a darle este concepto primero antes de responder a su pregunta, en funciones de JavaScript son objetos, también nula, de objetos, matrices y hasta la fecha, a fin de que se ve allí es no de una manera tan simple como typeof obj === 'objeto', por lo todo lo mencionado anteriormente devolverá verdadero , pero hay formas de verificarlo escribiendo una función o usando marcos JavaScript, OK:

Ahora, imagine que tiene este objeto que es un objeto real (no nulo, función o matriz):

var obj = {obj1: 'obj1', obj2: 'obj2'};

JavaScript puro:

//that's how it gets checked in angular framework
function isObject(obj) {
  return obj !== null && typeof obj === 'object';
}

o

//make sure the second object is capitalised 
function isObject(obj) {
   return Object.prototype.toString.call(obj) === '[object Object]';
}

o

function isObject(obj) {
    return obj.constructor.toString().indexOf("Object") > -1;
}

o

function isObject(obj) {
    return obj instanceof Object;
}

Simplemente puede usar una de estas funciones como se indica arriba en su código llamándolas y devolverá verdadero si es un objeto:

isObject(obj);

Si está utilizando un marco de JavaScript, generalmente han preparado este tipo de funciones para usted, estas son algunas de ellas:

jQuery:

 //It returns 'object' if real Object;
 jQuery.type(obj);

Angular:

angular.isObject(obj);

Subrayar y Lodash:

//(NOTE: in Underscore and Lodash, functions, arrays return true as well but not null)
_.isObject(obj);

También desea comprobar que no es una matriz. entonces la función esObjeto (obj) {return obj! == null && typeof obj === 'objeto' &&! Array.isArray (obj); }
Matt Goo

Estoy de acuerdo con usted, pero como puede ver en el comentario, así es como se hace en angularJs y lo menciono en el comentario frente a la función, cuentan la matriz como un objeto ... mire aquí para obtener más información: documentos .angularjs.org / api / ng / function / angular.isObject
Alireza

24

Depende de lo que quieras decir con "es un objeto". Si desea todo lo que no es primitivo , es decir, cosas en las que puede establecer nuevas propiedades, esto debería ser el truco:

function isAnyObject(value) {
    return value != null && (typeof value === 'object' || typeof value === 'function');
}

Excluye las primitivas (números de civil / NaN/ Infinity, las cadenas de fricción, símbolos, true/ false, undefinedy null), pero debe devolver cierto para todo lo demás (incluyendo Number, Booleany Stringobjetos). Tenga en cuenta que JS no define qué objetos "host", como windowo console, deberían devolver cuando se usa contypeof , por lo que es difícil cubrirlos con un cheque como este.

Si desea saber si algo es un objeto "simple", es decir, se creó como literal {}o con Object.create(null), puede hacer esto:

function isPlainObject(value) {
    if (Object.prototype.toString.call(value) !== '[object Object]') {
        return false;
    } else {
        var prototype = Object.getPrototypeOf(value);
        return prototype === null || prototype === Object.prototype;
    }
}

Editar 2018 : como Symbol.toStringTagahora permite personalizar la salida de Object.prototype.toString.call(...), la isPlainObjectfunción anterior podría volver falseen algunos casos incluso cuando el objeto comenzó su vida como un literal. Podría decirse que, por convención, un objeto con una etiqueta de cadena personalizada ya no es exactamente un objeto simple, pero esto ha enturbiado aún más la definición de qué es un objeto simple en Javascript.


¿Por qué se considera typeof === 'function' como un objeto? Una función no es un objeto, ¿no? "new myFunc ()" se convertirá en un objeto, sí, ¿pero en una función simple?
StanE

No, cada función es un objeto en Javascript, independientemente de cómo se creó. Puede establecer propiedades en ellos (a menos que estén congelados), lo son instanceof Object, dos literales de función idénticos no son estrictamente iguales, se pasan por referencia, etc.
último hijo

21

Dios mío, demasiada confusión en otras respuestas.

Respuesta corta

typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array)

Para probar esto, simplemente ejecute las siguientes declaraciones en la consola de Chrome.

Caso 1.

var anyVar = {};
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array) // true

Caso 2.

anyVar = [];
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array) // false

Caso 3.

anyVar = null;
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array); // false

Explicación

Ok, vamos a descomponerlo

typeof anyVar == 'object' se devuelve verdadero de tres candidatos: [], {} and null ,

anyVar instanceof Object reduce estos candidatos a dos: [], {}

!(anyVar instanceof Array) se reduce a uno solo {}

¡Tambores por favor!

Con esto, es posible que ya haya aprendido cómo verificar la matriz en Javascript.


2
Es de destacar que esto también regresa false(como se desee) cuando anyVares una función.
Jamie Birch

18

La forma más razonable de verificar el tipo de un valor parece ser el typeofoperador. El único problema es que está horriblemente roto:

  • Vuelve "object"pornull , que pertenece al tipo nulo.
  • Vuelve "function" objetos invocables, que pertenecen al tipo de objeto.
  • Puede devolver (casi) cualquier cosa que desee para objetos no estándar no invocables. Por ejemplo, a IE parecía gustarle "unknown". Los únicos resultados prohibidos son "function"los tipos primitivos.

typeofsolo es confiable para los no nullprimitivos. Entonces, una forma de verificar si un valor es un objeto sería asegurar que la cadena devuelta por typeofno corresponda a una primitiva, y que el objeto no lo sea null. Sin embargo, el problema es que un estándar futuro podría introducir un nuevo tipo primitivo, y nuestro código lo consideraría un objeto. Los nuevos tipos no aparecen con frecuencia, pero por ejemplo ECMAScript 6 introdujo el tipo de símbolo.

Por lo tanto, en lugar de typeof , solo recomiendo enfoques cuyo resultado varía dependiendo de si el valor es un objeto o no. Lo siguiente pretende ser un

Lista exhaustiva pero no exhaustiva de formas adecuadas de probar si un valor pertenece al tipo de objeto.

  • Object constructor

    El Objectconstructor coacciona el argumento pasado a un objeto. Si ya es un objeto, se devuelve el mismo objeto.

    Por lo tanto, puede usarlo para forzar el valor de un objeto y comparar estrictamente ese objeto con el valor original.

    La siguiente función requiere ECMAScript 3, que introdujo ===:

    function isObject(value) { /* Requires ECMAScript 3 or later */
      return Object(value) === value;
    }

    Me gusta este enfoque porque es simple y autodescriptivo, y una verificación análoga también funcionará para booleanos, números y cadenas. Sin embargo, tenga en cuenta que se basa en que lo global Objectno se oculta ni se modifica.

  • Constructores

    Cuando crea una instancia de un constructor, puede devolver un valor diferente de la instancia recién creada. Pero ese valor será ignorado a menos que sea un objeto.

    La siguiente función requiere ECMAScript 3, que permitió a los constructores devolver objetos que no son. Antes de ECMAScript 3 que arrojó un error, pero las trydeclaraciones no existían en ese entonces.

    function isObject(value) { /* Requires ECMAScript 3 or later */
      return new function() { return value; }() === value;
    }

    Si bien es un poco menos simple que el ejemplo anterior, este no se basa en ninguna propiedad global y, por lo tanto, podría ser el más seguro.

  • this valor

    Las antiguas especificaciones de ECMAScript requerían que el thisvalor fuera un objeto. Se introdujo ECMAScript 3 Function.prototype.call, que permitió llamar a una función con un thisvalor arbitrario , pero forzado a un objeto.

    ECMAScript 5 introdujo un modo estricto que eliminó este comportamiento, pero en modo descuidado todavía podemos (pero posiblemente no deberíamos) confiar en él.

    function isObject(value) { /* Requires ECMAScript 3 or later in sloppy mode */
      return function() { return this === value; }.call(value);
    }
  • [[Prototipo]]

    Todos los objetos ordinarios tienen una ranura interna llamada [[Prototipo]], cuyo valor determina de qué otro objeto hereda. El valor solo puede ser un objeto o null. Por lo tanto, puede intentar crear un objeto que herede del valor deseado y verificar si funcionó.

    Ambos Object.createy Object.getPrototypeOfrequieren ECMAScript 5.

    function isObject(value) { /* Requires ECMAScript 5 or later */
      try {
        Object.create(value);
        return value !== null;
      } catch(err) {
        return false;
      }
    }
    function isObject(value) { /* Requires ECMAScript 5 or later */
      function Constructor() {}
      Constructor.prototype = value;
      return Object.getPrototypeOf(new Constructor()) === value;
    }
  • Algunas nuevas formas de ECMAScript 6

    ECMAScript 6 presenta algunas nuevas formas indirectas de verificar si un valor es un objeto. Utilizan el enfoque visto anteriormente para pasar el valor a algún código que requiere un objeto, envuelto dentro de una trydeclaración para detectar errores. Algunos ejemplos ocultos, no vale la pena comentar


Nota: intencionalmente omití algunos enfoques como Object.getPrototypeOf(value)(ES5) y Reflectmétodos (ES6) porque llaman métodos internos esenciales que pueden hacer cosas desagradables, por ejemplo, si valuees un proxy. Por razones de seguridad, mis ejemplos solo hacen referencia valuesin acceder directamente.


2
"Solo mi respuesta y la de Daan son completamente correctas". es un poco presuntuoso dado que estoy totalmente en desacuerdo con tus dos primeras oraciones.
zzzzBov

1
@zzzzBov Bueno, miré todas las respuestas y no se aseguran de devolver siempre la respuesta correcta, excepto la mía y la de Daan. Puedo dar contraejemplos reproducibles a la mayoría de ellos. Los otros recomiendan verificar si typeof devuelve "función" u "objeto", pero como expliqué, la especificación permite otros resultados para algunos objetos. La respuesta de Matt Fenwick contiene la misma respuesta correcta que la de Daan, pero también contiene respuestas incorrectas.
Oriol

1
No estoy de acuerdo con la premisa de que su respuesta es "enteramente correcta", argumentando que otros "no se aseguran de devolver siempre la respuesta correcta" no refutan mi posición de ninguna manera. Además, la pregunta no hace ningún reclamo con respecto a qué entrada debería producir qué salida.
zzzzBov

1
@zzzzBov La pregunta pregunta cómo verificar si algo es un objeto. ECMAScript define qué es un objeto, así que uso esa definición. No puedo ver ninguna otra interpretación razonable. Las respuestas que hacen otras cosas (como excluir matrices) pueden ser útiles en algunas circunstancias, pero no comprueban si algo es un objeto.
Oriol


15

Prueba esto

if (objectName instanceof Object == false) {
  alert('Not an object');
}
else {
  alert('An object');
}

14
¿Por qué doblar cheques booleanos?
jkutianski

55
Esto pierde dos casos: Object.prototype instanceof Object-> falso. Object.create(null) instanceof Object-> falso.
Matt Fenwick

¿Qué pasa con las fechas? new Date() instanceof Object => verdadero
mauron85

13

Funciones listas para usar para verificar

function isObject(o) {
  return null != o && 
    typeof o === 'object' && 
    Object.prototype.toString.call(o) === '[object Object]';
}

function isDerivedObject(o) {
  return !isObject(o) && 
    null != o && 
    (typeof o === 'object' || typeof o === 'function') &&
    /^\[object /.test(Object.prototype.toString.call(o));
}

// Loose equality operator (==) is intentionally used to check
// for undefined too

// Also note that, even null is an object, within isDerivedObject
// function we skip that and always return false for null

Explicación

  • En Javascript, null, Object, Array, Datey functions son todos los objetos. Aunque, nulles un poco artificial. Por lo tanto, es mejor verificar el nullprimero, para detectar que no es nulo.

  • Comprobación de typeof o === 'object'garantías que oes un objeto. Sin esta comprobación, no Object.prototype.toStringtendría sentido, ya que devolvería el objeto para todo, ¡incluso para undefinedy null! Por ejemplo: toString(undefined)vuelve [object Undefined]!

    Después de la typeof o === 'object'verificación, toString.call (o) es un excelente método para verificar si oes un objeto, un objeto derivado como Array, Dateo a function.

  • En isDerivedObjectfunción, comprueba si oes una función. Porque, también funciona un objeto, por eso está ahí. Si no lo hizo, la función volverá como falsa. Ejemplo: isDerivedObject(function() {})volvería false, pero ahora vuelve true.

  • Siempre se puede cambiar la definición de lo que es un objeto. Entonces, uno puede cambiar estas funciones en consecuencia.


Pruebas

function isObject(o) {
  return null != o && 
    typeof o === 'object' && 
    Object.prototype.toString.call(o) === '[object Object]';
}

function isDerivedObject(o) {
  return !isObject(o) && 
    null != o && 
    (typeof o === 'object' || typeof o === 'function') &&
    /^\[object /.test(Object.prototype.toString.call(o));
}

// TESTS

// is null an object?

console.log(
  'is null an object?', isObject(null)
);

console.log(
  'is null a derived object?', isDerivedObject(null)
);

// is 1234 an object?

console.log(
  'is 1234 an object?', isObject(1234)
);

console.log(
  'is 1234 a derived object?', isDerivedObject(1234)
);

// is new Number(1234) an object?

console.log(
  'is new Number(1234) an object?', isObject(new Number(1234))
);

console.log(
  'is new Number(1234) a derived object?', isDerivedObject(1234)
);

// is function object an object?

console.log(
  'is (new (function (){})) an object?', 
  isObject((new (function (){})))
);

console.log(
  'is (new (function (){})) a derived object?', 
  isObject((new (function (){})))
);

// is {} an object?

console.log(
  'is {} an object?', isObject({})
);

console.log(
  'is {} a derived object?', isDerivedObject({})
);

// is Array an object?

console.log(
  'is Array an object?',
  isObject([])
)

console.log(
  'is Array a derived object?',
  isDerivedObject([])
)

// is Date an object?

console.log(
  'is Date an object?', isObject(new Date())
);

console.log(
  'is Date a derived object?', isDerivedObject(new Date())
);

// is function an object?

console.log(
  'is function an object?', isObject(function(){})
);

console.log(
  'is function a derived object?', isDerivedObject(function(){})
);


13

Si desea comprobar si el prototypepara un objectsolo proviene Object. Filtra String, Number, Array, Arguments, etc.

function isObject (n) {
  return Object.prototype.toString.call(n) === '[object Object]';
}

O como una función de flecha de expresión única (ES6 +)

const isObject = n => Object.prototype.toString.call(n) === '[object Object]'

1
esta es la mejor manera, pero lo haría aún más fácil en la segunda línea:return Object.prototype.toString.call(n) === '[object Object]'
mesqueeb

1
También puede quitar el nullcheque, porqueObject.prototype.toString.call(null) === '[object Null]'
Gust van de Wal

12
var a = [1]
typeof a //"object"
a instanceof Object //true
a instanceof Array //true

var b ={a: 1}
b instanceof Object //true
b instanceof Array //false

var c = null
c instanceof Object //false
c instanceof Array //false

Me pidieron que proporcionara más detalles. La forma más limpia y comprensible de verificar si nuestra variable es un objeto es typeof myVar. Devuelve una cadena con un tipo (por ejemplo "object","undefined" ).

Desafortunadamente, Array y null también tienen un tipo object. Para tomar solo objetos reales, es necesario verificar la cadena de herencia utilizando el instanceofoperador. Eliminará nulo, pero Array tiene Objeto en la cadena de herencia.

Entonces la solución es:

if (myVar instanceof Object && !(myVar instanceof Array)) {
  // code for objects
}

/./ instanceof Object //true
yckart

11

Poco tarde ... para "objetos simples" (quiero decir, como {'x': 5, 'y': 7}) tengo este pequeño fragmento:

function isPlainObject(o) {
   return ((o === null) || Array.isArray(o) || typeof o == 'function') ?
           false
          :(typeof o == 'object');
}

Genera el siguiente resultado:

console.debug(isPlainObject(isPlainObject)); //function, false
console.debug(isPlainObject({'x': 6, 'y': 16})); //literal object, true
console.debug(isPlainObject(5)); //number, false
console.debug(isPlainObject(undefined)); //undefined, false
console.debug(isPlainObject(null)); //null, false
console.debug(isPlainObject('a')); //string, false
console.debug(isPlainObject([])); //array?, false
console.debug(isPlainObject(true)); //bool, false
console.debug(isPlainObject(false)); //bool, false

Siempre funciona para mi. If devolverá "verdadero" solo si el tipo de "o" es "objeto", pero no nulo, o matriz, o función. :)


Como se mencionó en las respuestas anteriores, su enfoque fallará en el caso del objeto Fecha.
Grzegorz Pawlik

9

lodash tiene isPlainObject , que podría ser lo que buscan muchos de los que vienen a esta página. Devuelve falso cuando da una función o matriz.


¡Perfecto! Sabía _.isObjectqué coincide con lo que JS considera un objeto. Pero lo que generalmente necesito es diferenciar, por ejemplo, un objeto literal y una matriz, que es exactamente lo que _.isPlainObjectme permite hacer.
Lima

9

Esto funcionará Es una función que devuelve verdadero, falso o posiblemente nulo.

const isObject = obj => obj && obj.constructor && obj.constructor === Object;

console.log(isObject({})); // true
console.log(isObject([])); // false
console.log(isObject(new Function)); // false
console.log(isObject(new Number(123))); // false
console.log(isObject(null)); // null


2
@SeregPie En el futuro, debe abstenerse de editar el código en las respuestas. Tal como está esta respuesta, cuando hice la prueba obtuve nullel resultado de la prueba final en lugar de hacerlo false. Consulte ¿ Cuándo debo hacer modificaciones al código?
Nick

9

Dado que parece haber mucha confusión sobre cómo manejar este problema correctamente, dejaré mis 2 centavos (esta respuesta cumple con las especificaciones y produce resultados correctos en todas las circunstancias):

Prueba de primitivas: undefined null boolean string number

function isPrimitive(o){return typeof o!=='object'||null}

Un objeto no es un primitivo:

function isObject(o){return !isPrimitive(o)}

O alternativamente:

function isObject(o){return o instanceof Object}
function isPrimitive(o){return !isObject(o)}

Prueba de cualquier matriz:

const isArray=(function(){
    const arrayTypes=Object.create(null);
    arrayTypes['Array']=true;
    arrayTypes['Int8Array']=true;
    arrayTypes['Uint8Array']=true;
    arrayTypes['Uint8ClampedArray']=true;
    arrayTypes['Int16Array']=true;
    arrayTypes['Uint16Array']=true;
    arrayTypes['Int32Array']=true;
    arrayTypes['Uint32Array']=true;
    arrayTypes['BigInt64Array']=true;
    arrayTypes['BigUint64Array']=true;
    arrayTypes['Float32Array']=true;
    arrayTypes['Float64Array']=true;
    return function(o){
        if (!o) return false;
        return !isPrimitive(o)&&!!arrayTypes[o.constructor.name];
    }
}());

Prueba de objeto excluido: Date RegExp Boolean Number String Functioncualquier matriz

const isObjectStrict=(function(){
    const nativeTypes=Object.create(null);
    nativeTypes['Date']=true;
    nativeTypes['RegExp']=true;
    nativeTypes['Boolean']=true;
    nativeTypes['Number']=true;
    nativeTypes['String']=true;
    nativeTypes['Function']=true;
    return function(o){
        if (!o) return false;
        return !isPrimitive(o)&&!isArray(o)&&!nativeTypes[o.constructor.name];
    }
}());

8

Cuando todo lo demás falla, uso esto:

var isObject = function(item) {
   return item.constructor.name === "Object";
}; 

1
¿Por qué la comparación de cadenas, por qué no simplemente item.constructor === Object?
K3 --- rnc

nulllanza una excepciónUncaught TypeError: Cannot read property 'constructor' of null(…)
Vitim.us

@rounce Tengo el objetivo de admitir versiones anteriores de IE, ¿por qué no funciona en IE? ¿Por el indexOfo por el constructor.name?
Jankapunkt

8

La biblioteca funcional Ramda tiene una función maravillosa para detectar tipos de JavaScript.

Parafraseando la función completa :

function type(val) {
  return val === null      ? 'Null'      :
         val === undefined ? 'Undefined' :
         Object.prototype.toString.call(val).slice(8, -1);
}

Tuve que reír cuando me di cuenta de lo simple y hermosa que era la solución.

Ejemplo de uso de la documentación de Ramda :

R.type({}); //=> "Object"
R.type(1); //=> "Number"
R.type(false); //=> "Boolean"
R.type('s'); //=> "String"
R.type(null); //=> "Null"
R.type([]); //=> "Array"
R.type(/[A-z]/); //=> "RegExp"
R.type(() => {}); //=> "Function"
R.type(undefined); //=> "Undefined"

8

Después de leer y probar una gran cantidad de implementaciones, me he dado cuenta de que muy pocas personas tratan de comprobar si hay valores como JSON, Math,document o los objetos con cadenas de prototipos más de 1 paso.

En lugar de verificar typeofnuestra variable y luego eliminar los casos límite, pensé que sería mejor si la verificación se mantuviera lo más simple posible para evitar tener que refactorizar cuando hay nuevas primitivas u objetos nativos agregados que se registran comotypeof 'objeto '.

Después de todo, el typeofoperador le dirá si algo es un objeto para JavaScript , pero la definición de JavaScript de un objeto es demasiado amplia para la mayoría de los escenarios del mundo real (por ejemplo typeof null === 'object'). A continuación se muestra una función que determina si la variable ves un objeto repitiendo esencialmente dos verificaciones:

  1. Se inicia un bucle que continúa mientras la versión en cadena de vis '[object Object]'.
    Quería que el resultado de la función fuera exactamente como los registros a continuación, así que este es el único criterio de "objetividad" con el que terminé. Si falla, la función devuelve falso de inmediato.
  2. vse reemplaza con el próximo prototipo en la cadena con v = Object.getPrototypeOf(v), pero también se evalúa directamente después. Cuando el nuevo valor de ves null, significa que cada prototipo, incluido el prototipo raíz (que bien podría haber sido el único prototipo dentro de la cadena) ha pasado la verificación en el ciclo while y podemos devolver verdadero. De lo contrario, comienza una nueva iteración.

function isObj (v) {
  while (     Object.prototype.toString.call(v) === '[object Object]')
  if    ((v = Object.getPrototypeOf(v))         === null)
  return true
  return false
}

console.log('FALSE:')
console.log('[]                   -> ', isObj([]))
console.log('null                 -> ', isObj(null))
console.log('document             -> ', isObj(document))
console.log('JSON                 -> ', isObj(JSON))
console.log('function             -> ', isObj(function () {}))
console.log('new Date()           -> ', isObj(new Date()))
console.log('RegExp               -> ', isObj(/./))

console.log('TRUE:')
console.log('{}                   -> ', isObj({}))
console.log('new Object()         -> ', isObj(new Object()))
console.log('new Object(null)     -> ', isObj(new Object(null)))
console.log('new Object({})       -> ', isObj(new Object({foo: 'bar'})))
console.log('Object.prototype     -> ', isObj(Object.prototype))
console.log('Object.create(null)  -> ', isObj(Object.create(null)))
console.log('Object.create({})    -> ', isObj(Object.create({foo: 'bar'})))
console.log('deep inheritance     -> ', isObj(Object.create(Object.create({foo: 'bar'}))))


6
if(typeof value === 'object' && value.constructor === Object)
{
    console.log("This is an object");
}

1
Si valuees nullesto arrojará un error ...
Gershom

Y, por supuesto, será falsepara el objeto Object.assign({}, {constructor: null}).
user4642212

6

Si explícitamente quiere verificar si el valor dado es {}.

function isObject (value) {
 return value && typeof value === 'object' && value.constructor === Object;
}

6
const isObject = function(obj) {
  const type = typeof obj;
  return type === 'function' || type === 'object' && !!obj;
};

!!objes una abreviatura para verificar si objes verdad (para filtrar null)


6

Es una vieja pregunta, pero pensé dejar esto aquí. La mayoría de las personas están verificando si la variable {}significa un valor clave emparejado y no cuál es la construcción de subrayado que JavaScript está usando para una cosa dada, porque para ser honesto, casi todo en JavaScript es un objeto. Así que quitando eso del camino. Si lo haces...

let x = function() {}
typeof x === 'function' //true
x === Object(x) // true
x = []
x === Object(x) // true

// also
x = null
typeof null // 'object'

La mayoría de las veces lo que queremos es saber si tenemos un objeto de recurso de una API o nuestra llamada a la base de datos devuelta desde el ORM. Entonces podemos probar si no es un Array, no nulles, no es typeof 'function', y es unObject

// To account also for new Date() as @toddmo pointed out

x instanceof Object && x.constructor === Object

x = 'test' // false
x = 3 // false
x = 45.6 // false
x = undefiend // false
x = 'undefiend' // false
x = null // false
x = function(){} // false
x = [1, 2] // false
x = new Date() // false
x = {} // true

aparece trueparanew Date()
toddmo

1
@toddmo gracias por señalar eso. Ahora el código de ejemplo devuelve false paranew Date()
Gilbert

4

Lo que me gusta usar es esto

function isObject (obj) {
  return typeof(obj) == "object" 
        && !Array.isArray(obj) 
        && obj != null 
        && obj != ""
        && !(obj instanceof String)  }

Creo que en la mayoría de los casos, una fecha debe pasar el cheque como un objeto, por lo que no filtro las fechas


4

Encontré una "nueva" forma de hacer este tipo de comprobación de tipo a partir de esta pregunta SO: ¿Por qué la instancia de devuelve falso para algunos literales?

a partir de eso, creé una función para la verificación de tipos de la siguiente manera:

function isVarTypeOf(_var, _type){
    try {
        return _var.constructor === _type;
    } catch(ex) {
        return false;         //fallback for null or undefined
    }
}

entonces solo puedes hacer:

console.log(isVarTypeOf('asdf', String));   // returns true
console.log(isVarTypeOf(new String('asdf'), String));   // returns true
console.log(isVarTypeOf(123, String));   // returns false
console.log(isVarTypeOf(123, Number));   // returns true
console.log(isVarTypeOf(new Date(), String));   // returns false
console.log(isVarTypeOf(new Date(), Number));   // returns false
console.log(isVarTypeOf(new Date(), Date));   // returns true
console.log(isVarTypeOf([], Object));   // returns false
console.log(isVarTypeOf([], Array));   // returns true
console.log(isVarTypeOf({}, Object));   // returns true
console.log(isVarTypeOf({}, Array));   // returns false
console.log(isVarTypeOf(null, Object));   // returns false
console.log(isVarTypeOf(undefined, Object));   // returns false
console.log(isVarTypeOf(false, Boolean));   // returns true

Esto se prueba en Chrome 56, Firefox 52, Microsoft Edge 38, Internet Explorer 11, Opera 43

editar:
si también desea verificar si una variable es nula o indefinida, puede usar esto en su lugar:

function isVarTypeOf(_var, _type){
    try {
        return _var.constructor === _type;
    } catch(ex) {
        return _var == _type;   //null and undefined are considered the same
        // or you can use === if you want to differentiate them
    }
}

var a = undefined, b = null;
console.log(isVarTypeOf(a, undefined)) // returns true
console.log(isVarTypeOf(b, undefined)) // returns true
console.log(isVarTypeOf(a, null)) // returns true

actualización del comentario de inanc: desafío aceptado: D

si quieres perder objetos de comparación puedes intentarlo de esta manera:

function isVarTypeOf(_var, _type, looseCompare){
    if (!looseCompare){
        try {
            return _var.constructor === _type;
        } catch(ex){
            return _var == _type;
        }
    } else {
        try{
            switch(_var.constructor){
                case Number:
                case Function:
                case Boolean:
                case Symbol:
                case Date:
                case String:
                case RegExp:
                    // add all standard objects you want to differentiate here
                    return _var.constructor === _type;
                case Error:
                case EvalError:
                case RangeError:
                case ReferenceError:
                case SyntaxError:
                case TypeError:
                case URIError:
                    // all errors are considered the same when compared to generic Error
                    return (_type === Error ? Error : _var.constructor) === _type;
                case Array:
                case Int8Array:
                case Uint8Array:
                case Uint8ClampedArray:
                case Int16Array:
                case Uint16Array:
                case Int32Array:
                case Uint32Array:
                case Float32Array:
                case Float64Array:
                    // all types of array are considered the same when compared to generic Array
                    return (_type === Array ? Array : _var.constructor) === _type;
                case Object:
                default:
                    // the remaining are considered as custom class/object, so treat it as object when compared to generic Object
                    return (_type === Object ? Object : _var.constructor) === _type;
            }
        } catch(ex){
            return _var == _type;   //null and undefined are considered the same
            // or you can use === if you want to differentiate them
        }
    }
}

de esa manera, puedes hacer como el comentario de inanc:

isVarTypeOf(new (function Foo(){}), Object); // returns false
isVarTypeOf(new (function Foo(){}), Object, true); // returns true

o

Foo = function(){};
Bar = function(){};
isVarTypeOf(new Foo(), Object);   // returns false
isVarTypeOf(new Foo(), Object, true);   // returns true
isVarTypeOf(new Bar(), Foo, true);   // returns false
isVarTypeOf(new Bar(), Bar, true);   // returns true
isVarTypeOf(new Bar(), Bar);    // returns true

Esto no puede detectar si una nueva clase es un objeto. isVarTypeOf (new (function Foo () {}), Object) // Esto devuelve falso en lugar de verdadero. Vea mi respuesta a continuación para una verificación adecuada.
Inanc Gumus

Sin embargo, puede usar instanceofpara buscar objetos. Aún así, esto no es una ciencia exacta.
Inanc Gumus

@inanc, así que se debe a que new Foo()devuelve un Fooobjeto, igual que new String()devuelve un Stringobjeto, o new Date()devuelve un Dateobjeto, se pueden hacer Foo = function(){}; isVarTypeOf(new Foo(), Foo);también
am05mhz

Sí, eso es lo que digo en realidad: no estás comprobando si es un objeto en este momento.
Inanc Gumus

@inanc Cheers, estaba buscando una forma de verificar el tipo (no solo el objeto), llegué a esta página y a la otra página, luego me emocioné demasiado porque olvidé el contexto de esta pregunta, mi mal :)
am05mhz
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.