Como você verifica se um valor é um objeto em JavaScript?
Como você verifica se um valor é um objeto em JavaScript?
Respostas:
ATUALIZAÇÃO :
Essa resposta está incompleta e fornece resultados enganosos . Por exemplo, null
também é considerado do tipo object
JavaScript, 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!).
typeof
é um operador, então não há necessidade ()
.
typeof
retorna 'objeto' para nulo, que não é um objeto, e instanceof
não funciona para objetos criados usando Object.create(null)
.
Se typeof yourVariable === 'object'
, é um objeto ou nulo. Se você deseja excluir nulo, apenas faça-o typeof yourVariable === 'object' && yourVariable !== null
.
yourVariable !== null
uma prática melhor?
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.
typeof
porque 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
.
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]
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
Object.prototype
Function.prototype
Object
Function
function C(){}
- funções definidas pelo usuárioC.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árioMath
Array.prototype
{"a": 1, "b": 2}
- objetos criados usando notação literalnew Number(3)
- invólucros em torno de primitivosObject.create(null)
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.getPrototypeOf
que 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({})
obj === Object(obj)
retorna true
para matrizes.
var x = []; console.log(x === Object(x)); // return true
getPrototypeOf
não funciona, por exemplo, com proxies revogados, que são objetos, mas jogam.
({}).toString.apply(obj) === '[object Object]'
Isto distingue entre matrizes e objetos que não são matrizes
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;
};
return obj === Object(obj) && Object.prototype.toString.call(obj) !== '[object Array]'
null
também. Deve ser a resposta aceita.
Object.prototype.toString.call(myVar)
retornará:
"[object Object]"
se myVar é um objeto"[object Array]"
se myVar for uma matrizPara obter mais informações sobre isso e por que é uma boa alternativa ao typeof, confira este artigo .
typeof [] === 'object'
-> true
. É disso que você precisa desse método.
Object.prototype.toString.call(3)
-> "[object Number]"
. Object.prototype.toString.call(new Number(3))
-> "[object Number]
"
getType=function(obj){return Object.prototype.toString.call(obj).match(/\[object (\w+)\]/)[1];};
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
isObject
só funciona com literais de objeto. Se eu criar um tipo personalizado, crie uma instância do tipo e testá-lo, ele retornafalse
Boolean(a)
é mais longo, mas muito mais intuitivo. Só não use new Boolean(a)
: ( aqui está o porquê )!
{
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.
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 null
for ... se todos os três forem verdadeiros, retorne true
. Se alguma das três condições falhar, o &&
teste entrará em curto-circuito e false
será devolvido. O null
teste 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
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 length
atributo, 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.
length
propriedade 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.
length
propriedade (eu quis dizer que literais de objetos não têm length
atributo 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.
typeof null
é "object"
não "undefined"
.
Array.isArray
:function isObject(o) {
return o !== null && typeof o === 'object' && Array.isArray(o) === false;
}
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).
isObject
não funcionará no caso de Object.create(null)
por causa da implementação interna da Object.create
qual é explicada aqui, mas você pode usar isObject
em 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! 🙂
isDate
yourDateObject com o objetivo de escrever um código robusto, caso contrário, você terá um isObject
método quebradiço .
Date
no 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 .
Oh meu Deus! Eu acho que isso poderia ser mais curto do que nunca, vamos ver o seguinte:
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
tipo de objetos JavaScript (incluindo null
) retorna"object"
console.log(typeof null, typeof [], typeof {})
A verificação de suas constructor
propriedades 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
Function.name
retorna 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
Object.create(null)
e por que você faria isso de qualquer maneira ...?
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);
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
, undefined
e null
), mas deve retornar verdadeiro para tudo o resto (incluindo Number
, Boolean
e String
objetos). Observe que o JS não define com quais objetos "host", como window
ou 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.toStringTag
agora permite personalizar a saída de Object.prototype.toString.call(...)
, a isPlainObject
função acima pode retornar false
em 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.
instanceof Object
, dois literais de função idênticos não são estritamente iguais, são passados por referência, etc.
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.
false
(conforme desejado) quando anyVar
é uma função.
A maneira mais razoável de verificar o tipo de um valor parece ser o typeof
operador. O único problema é que está terrivelmente quebrado:
"object"
para null
, que pertence ao tipo Nulo."function"
para objetos que podem ser chamados, que pertencem ao tipo de objeto."unknown"
. Os únicos resultados proibidos são "function"
e tipos primitivos.typeof
é confiável apenas para não null
primitivos. Portanto, uma maneira de verificar se um valor é um objeto seria garantir que a sequência retornada por typeof
nã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
Object
construtor
O Object
construtor 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 Object
nã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 try
instruçõ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 this
valor fosse um objeto. Introduzido o ECMAScript 3 Function.prototype.call
, que permitiu chamar uma função com um this
valor 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.create
e Object.getPrototypeOf
requerem 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 try
instrução para detectar erros. Alguns exemplos ocultos, não vale a pena comentar
Nota: ignorei intencionalmente algumas abordagens como Object.getPrototypeOf(value)
(ES5) e Reflect
métodos (ES6) porque elas chamam métodos internos essenciais que podem fazer coisas desagradáveis, por exemplo, se value
for um proxy. Por razões de segurança, meus exemplos fazem referência apenas value
sem acessá-lo diretamente.
Tente isto
if (objectName instanceof Object == false) {
alert('Not an object');
}
else {
alert('An object');
}
Object.prototype instanceof Object
-> false. Object.create(null) instanceof Object
-> falso.
new Date() instanceof Object
=> true
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
Em Javascript, null
, Object
, Array
, Date
e function
s são todos os objetos. Embora, null
seja um pouco artificial. Portanto, é melhor verificar o null
primeiro, para detectar que não é nulo.
Verificando typeof o === 'object'
garantias que o
são um objeto. Sem essa verificação, não Object.prototype.toString
teria sentido, pois retornaria objeto para tudo, mesmo para undefined
e 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 o
um objecto, um objecto derivado como Array
, Date
ou um function
.
Na isDerivedObject
funçã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.
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(){})
);
Se você gostaria de verificar se o prototype
for 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]'
return Object.prototype.toString.call(n) === '[object Object]'
null
cheque, porqueObject.prototype.toString.call(null) === '[object Null]'
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 instanceof
operador. 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
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. :)
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.
_.isObject
que 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 _.isPlainObject
me permite fazer.
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
null
o resultado do teste final em vez de false
. Consulte Quando devo editar o código?
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
Function
qualquer 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];
}
}());
Quando tudo mais falha, eu uso isso:
var isObject = function(item) {
return item.constructor.name === "Object";
};
item.constructor === Object
?
null
lança uma exceçãoUncaught TypeError: Cannot read property 'constructor' of null(…)
indexOf
ou por causa de constructor.name
?
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"
Depois de ler e experimentar um monte de implementações, tenho notado que muito poucas pessoas tentam buscar por valores como JSON
, Math
, document
ou 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 typeof
operador 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:
v
for '[object Object]'
. 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'}))))
if(typeof value === 'object' && value.constructor === Object)
{
console.log("This is an object");
}
value
for null
isso lançará um erro ...
false
para o objeto Object.assign({}, {constructor: null})
.
É 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
true
paranew Date()
new Date()
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
instanceof
para verificar se há objetos. Ainda assim, essa não é uma ciência exata.
new Foo()
retorna um Foo
objeto, mesmo que new String()
retorna um String
objeto, ou new Date()
retorna um Date
objeto, você pode fazer Foo = function(){}; isVarTypeOf(new Foo(), Foo);
também
null
é um objeto).