Verifique se um valor é um objeto em JavaScript


1365

Como você verifica se um valor é um objeto em JavaScript?


4
Uma variável é uma variável. Pode se referir a um objeto. Além disso, você pode definir "objeto" - como mostram as respostas e os comentários, existem várias definições conflitantes (por exemplo, se nullé um objeto).

8
OP, IMO, você deve aceitar a resposta de @ Daan, pois é a melhor solução e deve ser listada acima de outras respostas para que seja vista primeiro. (Sem ofensa para os outros que também têm boas respostas.)
tiffon

2
IMHO realmente depende do que você (aquele que procura uma resposta para esta pergunta) considera um Objeto e por que está verificando. Esta pergunta fornece respostas diferentes se você estiver tentando distinguir matrizes (que são objetos) de outros objetos ou se estiver tentando separar valores escalares de "vetores". E se nulo (que é um Objeto, de acordo com typeof) ou Funções (que são Objetos) deve ser excluído ou não, isso realmente depende do motivo pelo qual você está verificando. É por isso que existem tantas respostas e a maioria delas, no contexto, está correta.
FrancescoMM

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

1
Seria ótimo se você pudesse começar dizendo o que exatamente você quer dizer com "é um objeto". (Ou diga explicitamente que parte da resposta que você procura é definir vários significados populares de "é um objeto" e depois diferenciá-los.) Na falta disso, todos estão falando um do outro.
Don escotilha

Respostas:


520

ATUALIZAÇÃO :

Essa resposta está incompleta e fornece resultados enganosos . Por exemplo, nulltambém é considerado do tipo objectJavaScript, sem mencionar vários outros casos extremos. Siga a recomendação abaixo e passe para a outra "resposta mais votada (e correta!)" .


Resposta original :

Tente usar typeof(var)e / ou var instanceof something.

EDIT: Essa resposta dá uma idéia de como examinar as propriedades de variáveis, mas é não uma receita à prova de balas (afinal de contas não há nenhuma receita em tudo!) Para verificar se ele é um objeto, longe disso. Como as pessoas tendem a procurar algo para copiar daqui sem fazer nenhuma pesquisa, eu recomendo que elas se voltem para a outra resposta mais votada (e correta!).


208
typeofé um operador, então não há necessidade ().
Yoshi

67
Sim, não precisa. Eu apenas prefiro assim.
Michael Krelin - hacker de

150
@ MichaelKrelin-hacker: Isso é lamentável, pois confunde as pessoas .
RightSaidFred

11
@RightSaidFred, não tenho explicação para isso, mas eu absolutamente não estou inclinado a adicionar suportes extras nestas expressões :)
Michael Krelin - hacker de

117
Esta resposta está incorreta. typeofretorna 'objeto' para nulo, que não é um objeto, e instanceofnão funciona para objetos criados usando Object.create(null).
Nikolai

1635

Se typeof yourVariable === 'object', é um objeto ou nulo. Se você deseja excluir nulo, apenas faça-o typeof yourVariable === 'object' && yourVariable !== null.


31
Funções também são objetos e devem ser incluídas no seu cheque.
precisa saber é o seguinte

4
Nesse caso, seria yourVariable !== nulluma prática melhor?
Hippietrail

9
@RightSaidFred Parece que typeof null == 'object'não será corrigido no ES6 . Eles disseram: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, a resposta simples é que as matrizes são consideradas objetos. Para uma resposta mais detalhada, você precisará ler typeofporque há alguns casos especiais que não fazem necessariamente muito sentido. Se você está tentando diferenciar matrizes e objetos que não são matrizes, definitivamente não deseja usar typeof.
Matt Fenwick

8
@ Tresdin A melhor maneira é correr Object.prototype.toString.call(yourVar), sendo sua Var o que você precisa inspecionar. Em caso de matrizes, Object.prototype.toString.call([1,2])retornos[object Array]
Jose Rui Santos

539

Vamos definir "objeto" em Javascript . De acordo com os documentos MDN , todo valor é um objeto ou um primitivo:

valor primitivo, primitivo

Um dado que não é um objeto e não possui nenhum método. O JavaScript possui 5 tipos de dados primitivos: sequência, número, booleano, nulo, indefinido.

O que é um primitivo?

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

O que é um objeto (ou seja, não é um primitivo)?

  • Object.prototype
  • tudo desceu de Object.prototype
    • Function.prototype
      • Object
      • Function
      • function C(){} - funções definidas pelo usuário
    • C.prototype- a propriedade prototype de uma função definida pelo usuário: este não C é um protótipo
      • new C() - "novo" - em uma função definida pelo usuário
    • Math
    • Array.prototype
      • matrizes
    • {"a": 1, "b": 2} - objetos criados usando notação literal
    • new Number(3) - invólucros em torno de primitivos
    • ... muitas outras coisas ...
  • Object.create(null)
  • tudo desceu de um Object.create(null)

Como verificar se um valor é um objeto

instanceof por si só não funcionará, porque perde dois casos:

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

typeof x === 'object'não funcionará, devido a falsos positivos ( null) e falsos negativos (funções):

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

Object.prototype.toString.call não funcionará, por causa de falsos positivos para todas as primitivas:

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

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

Então eu uso:

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

A resposta de @ Daan também parece funcionar:

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

porque, de acordo com os documentos MDN :

O construtor Object cria um wrapper de objeto para o valor fornecido. Se o valor for nulo ou indefinido, ele criará e retornará um objeto vazio; caso contrário, retornará um objeto de um tipo que corresponda ao valor especificado. Se o valor já for um objeto, ele retornará o valor.


Uma terceira maneira que parece funcionar (não tenho certeza se é 100%) é usar o Object.getPrototypeOfque gera uma exceção se o argumento não for um 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)retorna truepara matrizes.
Onur Yıldırım

5
var x = []; console.log(x === Object(x)); // return true
Illuminator

6
As matrizes @ Illuminator são objetos em Javascript, como mencionei na minha resposta.
Matt Fenwick

1
getPrototypeOfnão funciona, por exemplo, com proxies revogados, que são objetos, mas jogam.
Oriol

2
Por que não ({}).toString.apply(obj) === '[object Object]'Isto distingue entre matrizes e objetos que não são matrizes
MauricioJuanes

295

O underscore.js fornece o seguinte método para descobrir se algo é realmente um objeto:

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

ATUALIZAR

Devido a um erro anterior na V8 e à otimização menor da micro velocidade, o método é o seguinte desde underscore.js 1.7.0 (agosto de 2014):

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

57
Em javascript uma matriz é também um objeto, de modo que a maior parte do tempo que você deseja excluir a matriz:return obj === Object(obj) && Object.prototype.toString.call(obj) !== '[object Array]'
Daan

22
por que você excluiria uma matriz? Eles são objetos de pleno direito.
Nikolai

65
Porque na maioria das vezes você quiser distinguir um {} de um [], por exemplo, como entrada em uma função
Daan

5
@Nickolai ..e para iterar através de objetos aninhados.
Ricky Boyce

6
Ótima resposta. Alças nulltambém. Deve ser a resposta aceita.
tiffon 17/11/2015

180

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

  • "[object Object]" se myVar é um objeto
  • "[object Array]" se myVar for uma matriz
  • etc.

Para obter mais informações sobre isso e por que é uma boa alternativa ao typeof, confira este artigo .


12
Eu aprendi recentemente que typeof [] === 'object'-> true. É disso que você precisa desse método.
precisa saber é o seguinte

3
@Christophe Não faz distinção entre primitivos e objetos . Object.prototype.toString.call(3)-> "[object Number]". Object.prototype.toString.call(new Number(3))-> "[object Number]"
Matt Fenwick

3
@MattFenwick Eu não acho que este é o tipo de "objeto" do OP está tentando identificar
Christophe

3
@Christophe, por que você acha isso? IMHO, na ausência de qualquer outra definição dada pelo OP para "objeto", parece-me mais razoável concordar com o que é usado consistentemente em toda a especificação do ECS.
Matt Fenwick

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

116

Para simplesmente verificar contra Objeto ou Matriz sem chamada de função adicional (velocidade). Como também postado aqui .

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 () - Observação: use apenas para literais de objeto, pois retorna falso para objetos personalizados, como nova data ou novo 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

isObjectsó funciona com literais de objeto. Se eu criar um tipo personalizado, crie uma instância do tipo e testá-lo, ele retornafalse
WickyNilliams

3
@zupa: o que !! a faz?

4
@ 3000 bem, se deixarmos de fora a parte (!! a) ela trava, porque nulo e indefinido não têm construtores. (!! a) os filtra. Isso responde à sua pergunta?
Zupa

2
O @zupa @ 3000 Boolean(a)é mais longo, mas muito mais intuitivo. Só não use new Boolean(a): ( aqui está o porquê )!
precisa saber é o seguinte

10
Surpresa, a melhor resposta está tão abaixo na página. Isso basicamente responde à pergunta - isso seria representado no JSON como algo começando com um {caractere. Para o caso da matriz, desde que você não precise oferecer suporte ao IE <9, você pode usar Array.isArray()para determinar se algo é uma matriz. Ele passa em todos os casos de teste que você forneceu.
Kip

81

Gosto simplesmente:

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

Se o item for um objeto JS, e não for um array JS, e não nullfor ... se todos os três forem verdadeiros, retorne true. Se alguma das três condições falhar, o &&teste entrará em curto-circuito e falseserá devolvido. O nullteste pode ser omitido, se desejado (dependendo de como você usa null).

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
E o console.log (isObject (new Date ()))? Por que uma data deve ser um objeto, mas uma matriz não?
Schirrmacher

5
@macher Porque new Date()retorna um objeto. Uma matriz é, do ponto de vista lógico, não um objeto - embora o JavaScript manipule e relate-os como tal. Na prática, no entanto, não é útil vê-los iguais, porque não são. Um objeto não tem lengthatributo, por exemplo, e não possui métodos como push (). E, às vezes, você pode querer fornecer parâmetros de sobrecarga de função, onde é necessário fazer a diferença entre uma matriz ou um objeto, especialmente se outros parâmetros dependem de qual deles foi fornecido.
StanE 5/08/16

1
Matrizes @StanE são definitivamente objetos. Não sei por que você acha que os objetos não podem ter uma lengthpropriedade nem métodos como esse push, Object.create(Array.prototype)é um contra-exemplo trivial de um objeto sem matriz que os possui. O que torna as matrizes especiais é que elas são objetos exóticos com um método interno essencial personalizado, mas ainda são objetos.
Oriol

4
@ Oriol Eu não escrevi que matrizes não são objetos nem escrevi que objetos não podem ter uma lengthpropriedade (eu quis dizer que literais de objetos não têm lengthatributo por padrão). Eu escrevi que matrizes não são objetos do ponto de vista lógico . Eu estou falando sobre lógica do programa. Às vezes é necessário verificar se uma matriz é uma matriz "real" e definitivamente não é um objeto "real". É para isso que Array.isArray()serve. Imagine que você tem uma função que aceita um objeto ou uma matriz de objetos. Verificar um atributo ou método especial é uma solução suja. A maneira nativa é sempre melhor.
StanE 29/08/16

2
typeof nullé "object"não "undefined".
2540625 01/10

80

Com função Array.isArray:

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

Sem função Array.isArray:

Apenas surpreendi quantas votações positivas por respostas erradas 😮
Apenas 1 resposta passou nos meus testes !!! Aqui eu criei minha versão simplificada:

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

Quanto a mim, é claro e simples, e simplesmente funciona! Aqui estão meus testes:

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

MAIS UMA VEZ: nem todas as respostas passam nesses testes !!! 🙈


Caso você precise verificar se o objeto é uma instância de determinada classe , verifique o construtor com sua classe específica, como:

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

teste simples:

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

Como resultado, você terá um código rigoroso e robusto!


No caso de você não vai criar funções como isDate, isError, isRegExp, etc você pode considerar a opção de usar estas funções generalizadas:

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

não funcionará corretamente para todos os casos de teste mencionados anteriormente, mas é bom o suficiente para todos os objetos (simples ou construídos).


isObjectnão funcionará no caso de Object.create(null)por causa da implementação interna da Object.createqual é explicada aqui, mas você pode usar isObjectem uma implementação mais 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;
};

Já existe um pacote criado no npm v1 com base nesta implementação! E funciona para todos os casos de teste descritos anteriormente! 🙂


melhor resposta! funciona para muitos dos casos mencionados aqui
prieston

Como isso retorna false para isObject (myDateObject), essa não é uma resposta para a pergunta. Não informa se uma variável é um objeto, apenas se for um objeto de uma classe específica. A questão aqui é para uma função genérica que retorna true para qualquer objeto.
Yetanotherjosh

@ Yetanotherjosh Na verdade, é uma resposta: você mencionou o caso descrito na resposta e o ponto - você deve usar o isDateyourDateObject com o objetivo de escrever um código robusto, caso contrário, você terá um isObjectmétodo quebradiço .
V. Kovpak

@ VladimirKovpak O uso Dateno meu comentário foi mal escolhido porque sim, a resposta discute Date. Mas Dateé apenas uma das infinitas classes possíveis e o ponto vale para qualquer outra classe. Exemplo: class Foo() { }; var x = new Foo(); isObject(x)retorna false. Não sei exatamente qual é o caso de uso do OP, mas é fácil conceber cenários nos quais será inviável ter que conhecer todas as classes possíveis e verificar especificamente se cada uma delas .
precisa saber é o seguinte

@Yetanotherjosh Atualizei minha resposta. E adicionou mais 1 caso.
V. Kovpak

41

Oh meu Deus! Eu acho que isso poderia ser mais curto do que nunca, vamos ver o seguinte:

Código curto e 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 (incluindo null) retorna"object"

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

Verificando seus construtores

A verificação de suas constructorpropriedades retorna a função com seus nomes.

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

Apresentando Function.name

Function.nameretorna um nome somente leitura de uma função ou "anonymous"para fechamentos.

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 pode não funcionar no IE https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Browser_compatibility


3
Eu realmente gosto deste, curto e direto ao ponto. Ele só falha em uma coisa, tanto quanto eu posso ver. se obj = Object.create(null)e por que você faria isso de qualquer maneira ...?
Julian Knight

29

OK, vamos dar-lhe esse conceito antes de responder sua pergunta, em funções JavaScript são objetos, também nulo, Object, matrizes e até Data, de modo que você vê lá é não uma forma simples como typeof obj === 'objeto', então tudo o que foi mencionado acima retornará verdadeiro , mas há maneiras de verificar isso ao escrever uma função ou usar estruturas JavaScript, OK:

Agora, imagine que você tenha esse objeto que é um objeto real (não nulo, função ou 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';
}

ou

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

ou

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

ou

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

Você pode simplesmente usar uma dessas funções como acima em seu código chamando-as e ela retornará true se for um objeto:

isObject(obj);

Se você estiver usando uma estrutura JavaScript, eles geralmente preparam esse tipo de função para você, estas são algumas delas:

jQuery:

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

Angular:

angular.isObject(obj);

Sublinhado e Lodash:

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

Você também deseja verificar se não é uma matriz. então a função isObject (obj) {retorna obj! == null && typeof obj === 'objeto' &&! Array.isArray (obj); }
Matt Goo

Eu concordo com você, mas como você vê no comentário, é como é feito em angularJs e eu o mencionei no comentário na frente da função, eles contam a matriz como um objeto ... veja aqui para mais informações: docs .angularjs.org / api / ng / função / angular.isObject
Alireza

24

Depende do que você quer dizer com "é um objeto". Se você deseja tudo o que não é primitivo , ou seja, coisas nas quais você pode definir novas propriedades, isso deve fazer o truque:

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

Que exclui os primitivos (números simples / NaN/ Infinity, cordas simples, símbolos, true/ false, undefinede null), mas deve retornar verdadeiro para tudo o resto (incluindo Number, Booleane Stringobjetos). Observe que o JS não define com quais objetos "host", como windowou console, devem retornar quando usados typeof, portanto, é difícil cobrir esses itens com uma verificação como esta.

Se você quiser saber se algo é um objeto "simples", ou seja, foi criado como um literal {}ou com Object.create(null), você pode fazer o seguinte:

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.toStringTagagora permite personalizar a saída de Object.prototype.toString.call(...), a isPlainObjectfunção acima pode retornar falseem alguns casos, mesmo quando o objeto iniciou sua vida como um literal. Indiscutivelmente, por convenção, um objeto com uma tag de string personalizada não é mais exatamente um objeto simples, mas isso atrapalha ainda mais a definição do que é um objeto simples em Javascript.


Por que typeof === 'function' é considerado um objeto? Uma função não é um objeto, não é? "new myFunc ()" se tornará um objeto, sim, mas uma função simples?
StanE 5/08/16

Não, toda função é um objeto em Javascript, independentemente de como foi criada. Você pode definir propriedades nelas (a menos que estejam congeladas), são instanceof Object, dois literais de função idênticos não são estritamente iguais, são passados ​​por referência, etc.
last-child

21

Meu Deus, muita confusão em outras respostas.

Resposta curta

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

Para testar isso, execute as seguintes instruções no console do 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

Explicação

Ok. Vamos dividir

typeof anyVar == 'object'é retornado verdadeiro de três candidatos - [], {} and null,

anyVar instanceof Object reduz esses candidatos a dois - [], {}

!(anyVar instanceof Array) reduz a apenas um - {}

Rolos de tambor, por favor!

Por isso, você já deve ter aprendido a verificar a matriz em Javascript.


2
É importante notar que isso também retorna false(conforme desejado) quando anyVaré uma função.
Jamie Birch

18

A maneira mais razoável de verificar o tipo de um valor parece ser o typeofoperador. O único problema é que está terrivelmente quebrado:

  • Retorna "object"para null, que pertence ao tipo Nulo.
  • Ele retorna "function"para objetos que podem ser chamados, que pertencem ao tipo de objeto.
  • Ele pode retornar (quase) tudo o que desejar para objetos não-solicitáveis ​​não-padrão. Por exemplo, o IE parecia gostar "unknown". Os únicos resultados proibidos são "function"e tipos primitivos.

typeofé confiável apenas para não nullprimitivos. Portanto, uma maneira de verificar se um valor é um objeto seria garantir que a sequência retornada por typeofnão corresponda a uma primitiva e que o objeto não seja null. No entanto, o problema é que um padrão futuro pode introduzir um novo tipo primitivo, e nosso código consideraria um objeto. Novos tipos não aparecem com frequência, mas, por exemplo, o ECMAScript 6 introduziu o tipo de símbolo.

Portanto, em vez de typeof, apenas recomendo abordagens cujo resultado varia dependendo se o valor é um objeto ou não. O seguinte pretende ser um

Lista abrangente, mas não exaustiva, de maneiras adequadas de testar se um valor pertence ao tipo de Objeto.

  • Object construtor

    O Objectconstrutor coage o argumento passado para um objeto. Se já é um objeto, o mesmo objeto é retornado.

    Portanto, você pode usá-lo para coagir o valor a um objeto e comparar estritamente esse objeto com o valor original.

    A seguinte função requer o ECMAScript 3, que foi introduzido ===:

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

    Eu gosto dessa abordagem porque é simples e auto-descritiva, e uma verificação análoga também funcionará para booleanos, números e seqüências de caracteres. No entanto, esteja ciente de que depende do global Objectnão ser sombreado nem alterado.

  • Construtores

    Quando você instancia um construtor, ele pode retornar um valor diferente da instância recém-criada. Mas esse valor será ignorado, a menos que seja um objeto.

    A função a seguir requer o ECMAScript 3, que permitiu que os construtores retornassem objetos não. Antes do ECMAScript 3, gerava um erro, mas as tryinstruções não existiam na época.

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

    Embora um pouco menos simples que o exemplo anterior, este não depende de nenhuma propriedade global e, portanto, pode ser o mais seguro.

  • this valor

    As especificações antigas do ECMAScript exigiam que o thisvalor fosse um objeto. Introduzido o ECMAScript 3 Function.prototype.call, que permitiu chamar uma função com um thisvalor arbitrário , mas coagido a um objeto.

    O ECMAScript 5 introduziu um modo estrito que removeu esse comportamento, mas no modo desleixado ainda podemos (mas provavelmente não devemos) confiar nele.

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

    Todos os objetos comuns têm um slot interno chamado [[Prototype]], cujo valor determina de qual outro objeto é herdado. O valor pode ser apenas um objeto ou null. Portanto, você pode tentar criar um objeto que herda do valor desejado e verificar se funcionou.

    Ambos Object.createe Object.getPrototypeOfrequerem 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;
    }
  • Algumas novas maneiras do ECMAScript 6

    O ECMAScript 6 apresenta algumas novas maneiras indiretas de verificar se um valor é um objeto. Eles usam a abordagem vista anteriormente para passar o valor para algum código que requer um objeto, envolvido dentro de uma tryinstrução para detectar erros. Alguns exemplos ocultos, não vale a pena comentar


Nota: ignorei intencionalmente algumas abordagens como Object.getPrototypeOf(value)(ES5) e Reflectmétodos (ES6) porque elas chamam métodos internos essenciais que podem fazer coisas desagradáveis, por exemplo, se valuefor um proxy. Por razões de segurança, meus exemplos fazem referência apenas valuesem acessá-lo diretamente.


2
"Apenas minha resposta e a de Daan estão totalmente corretas." é um pouco presunçoso, uma vez que discordo inteiramente de suas duas primeiras frases.
ZzzzBov 02/09/16

1
@zzzzBov Bem, eu olhei para todas as respostas e elas não garantem sempre retornar a resposta correta, exceto a minha e a de Daan. Eu posso dar contra-exemplos reprodutíveis para a maioria deles. Os outros recomendam verificar se typeof retorna "function" ou "object", mas, como expliquei, a especificação permite outros resultados para alguns objetos. A resposta de Matt Fenwick contém a mesma resposta correta que a de Daan, mas também contém as incorretas.
Oriol

1
Discordei da premissa de que sua resposta é "totalmente correta", argumentando que outros "nem sempre garantem a resposta correta" não refuta minha posição de forma alguma. Além disso, a pergunta não faz nenhuma reivindicação sobre qual entrada deve produzir qual saída.
ZzzzBov

1
@zzzzBov A pergunta pergunta como verificar se algo é um objeto. ECMAScript define o que é um objeto, então eu uso essa definição. Não vejo outra interpretação razoável. Respostas que fazem outras coisas (como excluir matrizes) podem ser úteis em algumas circunstâncias, mas não verificam se algo é um objeto.
Oriol

@Oriol Talvez você possa fornecer uma resposta a esta pergunta Por que não existe um método interno em JavaScript para verificar se um objeto é simples? ?
precisa saber é o seguinte

15

Tente isto

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

14
Por que você dobule verifica booleanos?
Jkutianski

5
Isso perde dois casos: Object.prototype instanceof Object-> false. Object.create(null) instanceof Object-> falso.
Matt Fenwick

e as datas? new Date() instanceof Object => true
mauron85

13

Pronto para usar funções para verificação

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

Explicação

  • Em Javascript, null, Object, Array, Datee functions são todos os objetos. Embora, nullseja um pouco artificial. Portanto, é melhor verificar o nullprimeiro, para detectar que não é nulo.

  • Verificando typeof o === 'object'garantias que osão um objeto. Sem essa verificação, não Object.prototype.toStringteria sentido, pois retornaria objeto para tudo, mesmo para undefinede null! Por exemplo: toString(undefined)retorna [object Undefined]!

    Após a typeof o === 'object'verificação, toString.call (O) é um excelente método para verificar se oum objecto, um objecto derivado como Array, Dateou um function.

  • Na isDerivedObjectfunção, verifica se a oé uma função. Porque, função também um objeto, é por isso que está lá. Se não fez isso, a função retornará como falsa. Exemplo: isDerivedObject(function() {})retornaria false, porém agora retorna true.

  • Sempre se pode mudar a definição do que é um objeto. Assim, pode-se alterar essas funções adequadamente.


Testes

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

Se você gostaria de verificar se o prototypefor for é o objectúnico Object. Filtra String, Number, Array, Arguments, etc.

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

Ou como uma função de seta de expressão única (ES6 +)

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

1
este é o melhor caminho, mas gostaria de torná-lo ainda mais fácil, na 2ª linha:return Object.prototype.toString.call(n) === '[object Object]'
mesqueeb

1
Você também pode remover o 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 pediram para fornecer mais detalhes. A maneira mais limpa e compreensível de verificar se nossa variável é um objeto typeof myVar. Retorna uma string com um tipo (por exemplo "object", "undefined").

Infelizmente, Array e null também têm um tipo object. Para pegar apenas objetos reais, é necessário verificar a cadeia de herança usando o instanceofoperador. Ele eliminará nulo, mas a Matriz possui Objeto na cadeia de herança.

Então a solução é:

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

/./ instanceof Object //true
yckart

11

Um pouco tarde ... para "objetos simples" (quero dizer, como {'x': 5, 'y': 7}) eu tenho esse pequeno trecho:

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

Ele gera a próxima saída:

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

Sempre funciona para mim. If retornará "true" apenas se o tipo de "o" for "objeto", mas nenhum nulo, matriz ou função. :)


Conforme mencionado nas respostas anteriores, sua abordagem falhará no caso do objeto Date.
Grzegorz Pawlik

9

O lodash possui o isPlainObject , que pode ser o que muitos que acessam esta página estão procurando. Retorna false quando fornece uma função ou matriz.


Perfeito! Eu sabia sobre o _.isObjectque corresponde ao que JS considera um objeto. Mas o que eu normalmente preciso é diferenciar entre, por exemplo, um literal de objeto e uma matriz, que é exatamente o que _.isPlainObjectme permite fazer.
cal

9

Isso vai funcionar. É uma função que retorna verdadeiro, falso ou possivelmente 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 No futuro, você deve abster-se de editar o código nas respostas. Como esta resposta está, ao testar, obtive nullo resultado do teste final em vez de false. Consulte Quando devo editar o código?
Nick

9

Como parece haver muita confusão sobre como lidar com esse problema corretamente, deixarei meus 2 centavos (esta resposta é compatível com as especificações e produz resultados corretos em todas as circunstâncias):

Teste de primitivos: undefined null boolean string number

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

Um objeto não é um primitivo:

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

Ou alternativamente:

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

Teste para qualquer 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];
    }
}());

Teste para objeto excluindo: Date RegExp Boolean Number String Functionqualquer 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

Quando tudo mais falha, eu uso isso:

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

1
Por que a comparação de strings, por que não simplesmente item.constructor === Object?
K3 --- rnc 27/02

nulllança uma exceçãoUncaught TypeError: Cannot read property 'constructor' of null(…)
Vitim.us 17/05

@rounce Estou com o objetivo de suportar versões mais antigas do IE, por que não funciona no IE? Por causa do indexOfou por causa de constructor.name?
Jankapunkt

8

A biblioteca funcional Ramda tem uma função maravilhosa para detectar tipos de JavaScript.

Parafraseando a função completa :

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

Eu tive que rir quando percebi como a solução era simples e bonita.

Exemplo de uso da documentação do 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

Depois de ler e experimentar um monte de implementações, tenho notado que muito poucas pessoas tentam buscar por valores como JSON, Math, documentou objetos com correntes protótipo mais de 1 passo.

Em vez de verificar o typeof variável e remover os casos extremos, pensei que seria melhor se a verificação fosse mantida o mais simples possível para evitar refatorar quando houver novos primitivos ou objetos nativos adicionados que sejam registrados como typeof'object '

Afinal, o typeofoperador dirá se algo é um objeto para JavaScript , mas a definição de objeto de JavaScript é muito ampla para a maioria dos cenários do mundo real (por exemplo typeof null === 'object'). Abaixo está uma função que determina se a variávelv é um objeto repetindo essencialmente duas verificações:

  1. É iniciado um loop que continua enquanto a versão string vfor '[object Object]'.
    Eu queria que o resultado da função fosse exatamente como os logs abaixo, então esse é o único critério de "objetividade" com o qual acabei. Se falhar, a função retornará falso imediatamente.
  2. vé substituído pelo próximo protótipo da cadeia por v = Object.getPrototypeOf(v), mas também é avaliado diretamente depois. Quando o novo valor de vé null, significa que todo protótipo, incluindo o protótipo raiz (que poderia muito bem ter sido o único protótipo dentro da cadeia) passou na verificação no loop while e podemos retornar true. Caso contrário, uma nova iteração será iniciada.

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
Se valuefor nullisso lançará um erro ...
Gershom

E é claro que será falsepara o objeto Object.assign({}, {constructor: null}).
user4642212

6

Se desejar explicitamente verificar se o valor fornecido é {}.

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;
};

!!objé uma abreviação para verificar se objé verdade (para filtrar null)


6

É uma pergunta antiga, mas pensamos em deixar isso aqui. A maioria das pessoas está verificando se a variável está {}significando um valor-chave emparelhado e não qual é a construção sublinhada que o JavaScript está usando para uma determinada coisa, porque, para ser sincero, tudo o que é JavaScript é um objeto. Então, tirando isso do caminho. Se você fizer...

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

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

Na maioria das vezes, o que queremos é saber se temos um objeto de recurso de uma API ou nossa chamada de banco de dados retornada do ORM. Podemos então testar se não é um Array, não nullé, não é typeof 'function'e é umObject

// 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 obrigado por apontar isso. Agora o código de exemplo retorna falso paranew Date()
Gilbert

4

O que eu gosto de usar é este

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

Acho que, na maioria dos casos, uma Data deve passar na verificação como um Objeto, para não filtrar as datas.


4

Eu encontrei uma maneira "nova" de fazer exatamente esse tipo de verificação de tipo nesta pergunta do SO: Por que instanceof retorna false para alguns literais?

a partir disso, criei uma função para verificação de tipo da seguinte maneira:

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

então você pode fazer:

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

isso é testado no Chrome 56, Firefox 52, Microsoft Edge 38, Internet Explorer 11, Opera 43

editar:
se você também deseja verificar se uma variável é nula ou indefinida, você pode usar isso:

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

atualização do comentário do inanc: desafio aceito: D

se você quiser perder objetos de comparação, tente desta maneira:

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
        }
    }
}

Dessa forma, você pode fazer como o comentário de inanc:

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

ou

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

Isso não pode detectar se uma nova classe é um objeto. isVarTypeOf (new (function Foo () {}), Object) // Retorna false em vez de true. Veja minha resposta abaixo para uma verificação adequada.
Inanc Gumus

No entanto, você pode usar instanceofpara verificar se há objetos. Ainda assim, essa não é uma ciência exata.
Inanc Gumus

@inanc, bem que é porque new Foo()retorna um Fooobjeto, mesmo que new String()retorna um Stringobjeto, ou new Date()retorna um Dateobjeto, você pode fazer Foo = function(){}; isVarTypeOf(new Foo(), Foo);também
am05mhz

Sim, é o que digo na verdade: você não está verificando se é um objeto no momento.
Inanc Gumus

Felicidades @inanc, eu estava procurando uma maneira de fazer a verificação de tipo (não apenas objeto), cheguei a esta página e a outra página, então fiquei muito animado que eu esqueci o contexto desta pergunta, meu mau :)
am05mhz
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.