Verificando se existe uma chave em um objeto JavaScript?

2972

Como verifico se existe uma chave específica em um objeto ou matriz JavaScript?

Se uma chave não existir e eu tentar acessá-la, ela retornará falsa? Ou lançar um erro?

Adam Ernst
fonte
2
Tudo (quase tudo) no JavaScript é um Objeto ou pode ser convertido como um. É aqui que nascem as matrizes pseudo-associativas, como o @PatrickM apontou.
Andrew Larsson
este benchmark jsben.ch/#/WqlIl fornece uma visão geral sobre as maneiras mais comuns de como realizar essa verificação.
EscapeNetscape 24/10
uma solução rápida, geralmente eu ir para property.key = property.key || 'some default value', no caso de eu querer que a chave existir com algum valor a ela
RGLSV

Respostas:

4121

A verificação de indefinições não é uma maneira precisa de testar se existe uma chave. E se a chave existir, mas o valor for realmente undefined?

var obj = { key: undefined };
obj["key"] !== undefined // false, but the key exists!

Você deve usar o inoperador:

"key" in obj // true, regardless of the actual value

Se você deseja verificar se uma chave não existe, lembre-se de usar parênteses:

!("key" in obj) // true if "key" doesn't exist in object
!"key" in obj   // ERROR!  Equivalent to "false in obj"

Ou, se você deseja testar particularmente as propriedades da instância do objeto (e não as propriedades herdadas), use hasOwnProperty:

obj.hasOwnProperty("key") // true

Para uma comparação de desempenho entre os métodos que são in, hasOwnPropertye o principal undefined, consulte esta referência

Ates Goral
fonte
83
Ter uma propriedade com um valor definido manualmente de indefinido não faz absolutamente nenhum sentido. Seria realmente um oxímoro.
joebert
259
Estou convencido de que existem casos de uso para ter propriedades intencionalmente definidas como indefinidas.
Ates Goral 08/07/2009
168
Caso de uso válido: Gecko 1.9.1 [Firefox 3.5] não possui nenhuma propriedade window.onhashchange. O Gecko 1.9.2 [Firefox 3.6] tem essa propriedade definida como indefinida (até que o hash seja alterado). Para detectar o histórico de hash ou a versão do navegador, é necessário usar window.hasOwnProperty ("onhashchange");
SamGoody
7
Existe um problema semelhante no PHP, onde null == inexistente: stackoverflow.com/q/418066/372654 e, infelizmente, null também é útil lá.
Halil Özgür
80
@ joebert Só porque algo não faz sentido, não significa que você não o encontre no código de produção. Existem muitas bibliotecas que fazem coisas sem sentido.
Crashworks
298

resposta rápida

Como verifico se existe uma chave específica em um objeto ou matriz JavaScript? Se uma chave não existir e eu tentar acessá-la, ela retornará falsa? Ou lançar um erro?

Acessar diretamente uma propriedade ausente usando o estilo de matriz (associativo) ou o estilo de objeto retornará uma constante indefinida .

O lento e confiável no operador e no método hasOwnProperty

Como as pessoas já mencionaram aqui, você pode ter um objeto com uma propriedade associada a uma constante "indefinida".

 var bizzareObj = {valid_key:  undefined};

Nesse caso, você terá que usar o hasOwnProperty ou no operador para saber se a chave está realmente lá. Mas, mas a que preço?

então eu te digo ...

no operador e hasOwnProperty são "métodos" que usam o mecanismo do Descritor de propriedades em Javascript (semelhante ao reflexo de Java na linguagem Java).

http://www.ecma-international.org/ecma-262/5.1/#sec-8.10

O tipo de descritor de propriedades é usado para explicar a manipulação e reificação de atributos de propriedades nomeadas. Os valores do tipo Descritor de propriedades são registros compostos por campos nomeados em que o nome de cada campo é um nome de atributo e seu valor é um valor de atributo correspondente, conforme especificado em 8.6.1. Além disso, qualquer campo pode estar presente ou ausente.

Por outro lado, chamar um método ou chave de objeto usará o mecanismo Javascript [[Get]]. Isso é muito mais rápido!

referência

http://jsperf.com/checking-if-a-key-exists-in-a-javascript-array

Comparando Acesso Chave em JS.

Usando no operador
var result = "Impression" in array;

O resultado foi

12,931,832 ±0.21% ops/sec      92% slower 
Usando hasOwnProperty
var result = array.hasOwnProperty("Impression")

O resultado foi

16,021,758 ±0.45% ops/sec     91% slower
Acessando elementos diretamente (estilo colchetes)
var result = array["Impression"] === undefined

O resultado foi

168,270,439 ±0.13 ops/sec     0.02% slower 
Acessando elementos diretamente (estilo de objeto)
var result = array.Impression  === undefined;

O resultado foi

168,303,172 ±0.20%     fastest

EDIT: Qual é o motivo para atribuir a uma propriedade o undefinedvalor?

Essa pergunta me intriga. Em Javascript, há pelo menos duas referências para objetos ausentes para evitar problemas como este: nulle undefined.

nullé o valor primitivo que representa a ausência intencional de qualquer valor do objeto ou, em termos curtos, a falta de valor confirmada . Por outro lado, undefinedé um valor desconhecido (não definido). Se houver uma propriedade que será usada posteriormente com um valor adequado, considere usar nullreferência em vez de, undefinedporque no momento inicial, confirma-se que a propriedade não possui valor.

Comparar:

var a = {1: null}; 
console.log(a[1] === undefined); // output: false. I know the value at position 1 of a[] is absent and this was by design, i.e.:  the value is defined. 
console.log(a[0] === undefined); // output: true. I cannot say anything about a[0] value. In this case, the key 0 was not in a[].

Aconselhar

Evite objetos com undefinedvalores. Verifique diretamente sempre que possível e use nullpara inicializar os valores da propriedade. Caso contrário, use o inoperador ou hasOwnProperty()método lento .

EDIT: 12/04/2018 - NÃO É MAIS RELEVANTE

Como as pessoas comentaram, as versões modernas dos mecanismos Javascript (com exceção do Firefox) mudaram a abordagem para as propriedades de acesso. A implementação atual é mais lenta que a anterior para este caso específico, mas a diferença entre a chave de acesso e o objeto é negligenciável.

rdllopes
fonte
1
Todos esses métodos são aceitáveis ​​em todos os navegadores comumente usados, por exemplo, IE8 +?
Justin
11
+1 para avaliação comparativa. Obrigado, esta é exatamente a informação que eu esperava encontrar. Definitivamente, é um argumento forte para escrever código que nunca atribui ou espera que uma chave contenha o valor indefinido .
TJ Compton
Fiquei curioso para saber como o Underscore.js comparou (), então o adicionei ao jsperf ( versão 11 ). Acontece que ele está no grupo lento junto com in e hasOwnProperty ().
precisa saber é
3
Uma razão pela qual eu definiria indefinido para um valor de hash é que eu realmente queria excluir essa chave de propriedade do hash, mas delete hash[key]é muito mais lenta que isso hash[key] = undefined . É claro que, neste caso, não faz sentido para mim precisar do inoperador, mas atua como um contra-exemplo de "devemos sempre evitar definir valor como indefinido".
Alan Tam
1
Como o @ HüseyinYağlı mencionou, se você verificar o link jsperf , o desempenho mudou significativamente entre os diferentes métodos para a maioria dos navegadores, desde que esta resposta foi originalmente escrita. O Firefox é um dos poucos que ainda tem uma vantagem significativa usando os métodos de matriz ou objeto, mas para muitos outros navegadores as diferenças são insignificantes.
kevinmicke
144

Voltará undefined.

var aa = {hello: "world"};
alert( aa["hello"] );      // popup box with "world"
alert( aa["goodbye"] );    // popup box with "undefined"

undefinedé um valor constante especial. Então você pode dizer, por exemplo

// note the three equal signs so that null won't be equal to undefined
if( aa["goodbye"] === undefined ) {
    // do something
}

Esta é provavelmente a melhor maneira de verificar se há chaves ausentes. No entanto, como é indicado em um comentário abaixo, é teoricamente possível que você queira que o valor real seja undefined. Eu nunca precisei fazer isso e não consigo pensar em uma razão imediata por que eu desejaria, mas apenas por uma questão de perfeição, você pode usar o inoperador

// this works even if you have {"goodbye": undefined}
if( "goodbye" in aa ) {
    // do something
}
Eli Courtwright
fonte
8
E se a chave existir, mas o valor for realmente indefinido?
Ates Goral 08/07/2009
13
Você deve usar === em vez de == ao comparar com indefinido, caso contrário, nulo será comparado igual a indefinido.
Matthew Crumley
10
Eli, sua resposta não é completamente precisa. Porque de qualquer maneira (e é claro que isso nunca deve ser feito) indefinido não é um valor constante especial. Na verdade, não é uma palavra-chave reservada e você pode substituí-la, digamos, por exemplo, isso var undefined = 42;. Ao testar adereços indefinidos, você deve sempre usar ((typeof variable) === "undefined").
ssice
1
@ssice undefinednão é uma propriedade gravável acordo com a especificação ecma-international.org/ecma-262/5.1/#sec-15.1.1.3
therealrootuser
1
Nas versões anteriores do JavaScript, 'undefined' e 'NaN' eram variáveis ​​mutáveis ​​que podiam ser redefinidas ou atribuídas a outros valores . Isso foi uma coisa ruim. Foi fixado em ECMAScript 5.
jkdev
29
"key" in obj

Provavelmente está testando apenas valores de atributos de objetos muito diferentes das chaves da matriz

user2320522
fonte
Esse código também será verdadeiro para uma chave definida no protótipo de classe: function A () {}; A.prototype.b = 2; var a = new A (); Então 'b' em a é verdadeiro. Enquanto a.hasOwnProperty ('b') é obviamente falso.
Alexander Alexander
24

Três maneiras de verificar se uma propriedade está presente em um objeto javascript:

  1. !!obj.theProperty
    Converterá valor em bool. retorna truepara todos, exceto o falsevalor
  2. ' theProperty' in obj
    Retornará true se a propriedade existir, não importa seu valor (mesmo vazio)
  3. obj.hasOwnProperty('theProperty')
    Não verifica a cadeia de protótipos. (como todos os objetos têm o toStringmétodo, 1 e 2 retornam true nele, enquanto 3 podem retornar false nele).

Referência:

http://book.mixu.net/node/ch5.html

Lavi Avigdor
fonte
!! obj.theProperty falha quando o valor é indefinido. Ex:var a = {a : undefined, b : null}; !!a.a **will return false**
ARJUN
da revisão: !!obj.thePropertynão é uma solução para verificar se um objeto tem uma propriedade chamada theProperty. Ele falha para qualquer valor de propriedade falsey,, undefinednull, numérico 0ou NaN, e a string vazia""
traktor53
15

Se você estiver usando a biblioteca underscore.js , as operações de objeto / matriz tornam-se simples.

No seu caso, o método _.has pode ser usado. Exemplo:

yourArray = {age: "10"}

_.has(yourArray, "age")

retorna verdadeiro

Mas,

_.has(yourArray, "invalidKey")

retorna falso

vatsal
fonte
15

Responda:

if ("key" in myObj)
{
    console.log("key exists!");
}
else
{
    console.log("key doesn't exist!");
}

Explicação:

O inoperador verificará se a chave existe no objeto. Se você verificou se o valor era indefinido:, if (myObj["key"] === 'undefined')você pode ter problemas porque uma chave pode existir no seu objeto com o undefinedvalor.

Por esse motivo, é uma prática muito melhor usar primeiro o inoperador e comparar o valor que está dentro da chave depois que você já sabe que ela existe.

Webeng
fonte
12

Aqui está uma função auxiliar que eu acho bastante útil

Isso keyExists(key, search)pode ser usado para pesquisar facilmente uma chave em objetos ou matrizes!

Apenas passe a chave que deseja encontrar e pesquise obj (o objeto ou matriz) em que deseja encontrá-la.

function keyExists(key, search) {
        if (!search || (search.constructor !== Array && search.constructor !== Object)) {
            return false;
        }
        for (var i = 0; i < search.length; i++) {
            if (search[i] === key) {
                return true;
            }
        }
        return key in search;
    }

// How to use it:
// Searching for keys in Arrays
console.log(keyExists('apple', ['apple', 'banana', 'orange'])); // true
console.log(keyExists('fruit', ['apple', 'banana', 'orange'])); // false

// Searching for keys in Objects
console.log(keyExists('age', {'name': 'Bill', 'age': 29 })); // true
console.log(keyExists('title', {'name': 'Jason', 'age': 29 })); // false

Tem sido bastante confiável e funciona bem em vários navegadores.

jaredwilli
fonte
6
Isso parece um pouco confuso: em primeiro lugar, ao pesquisar uma matriz, esse método verifica se há um valor , não uma chave. Em segundo lugar, por que iterar através de uma matriz como essa quando você pode usar o Array.indexOfmétodo interno? (se você está procurando um valor, que é)
Nick F
9

vanila js

yourObjName.hasOwnProperty(key) : true ? false;

Se você deseja verificar se o objeto tem pelo menos uma propriedade em es2015

Object.keys(yourObjName).length : true ? false
Hajji Tarik
fonte
7

Solução ES6

usando Array#somee Object.keys. Ele retornará true se a chave fornecida existir no objeto ou false se não existir.

var obj = {foo: 'one', bar: 'two'};
    
function isKeyInObject(obj, key) {
    var res = Object.keys(obj).some(v => v == key);
    console.log(res);
}

isKeyInObject(obj, 'foo');
isKeyInObject(obj, 'something');

Exemplo de uma linha.

console.log(Object.keys({foo: 'one', bar: 'two'}).some(v => v == 'foo'));

usuário gentil
fonte
1
Ele falhará nas propriedades não numeráveis ​​do objeto.
Sid
@Sid me dê um exemplo.
tipo de usuário
Aqui está. deixe Josué = {nome: 'Josué', endereço: 'Londres'}; Object.defineProperty (joshua, 'isMarried', {valor: true, enumerável: false}); console.log ('isMarried' em Object.keys (joshua))
Sid
Estou aplicando sua solução no meu objeto. Não deveria estar dando certo para a primeira saída? console.log (Object.keys (joshua) .some (v => v == 'isMarried')); console.log (joshua.isMarried);
Sid
1
Sinto muito, mas você verificou a saída da segunda instrução do console? Object.defineProperty é equivalente a definir a propriedade usando a notação de ponto.
Sid
6

Podemos usar - hasOwnProperty.call(obj, key);

A maneira underscore.js -

if(_.has(this.options, 'login')){
  //key 'login' exists in this.options 
}

_.has = function(obj, key) {
  return hasOwnProperty.call(obj, key);
};
Mohan Dere
fonte
5

A maneira mais fácil de verificar é

"key" in object

por exemplo:

var obj = {
  a: 1,
  b: 2,
}
"a" in obj // true
"c" in obj // false

O valor retornado como true implica que a chave existe no objeto.

shekhardtu
fonte
4

Para aqueles que lodashincluíram em seu projeto:
Existe um método lodash _.get que tenta obter chaves "profundas":

Obtém o valor no caminho do objeto. Se o valor resolvido for indefinido, o defaultValue será retornado em seu lugar.

var object = { 'a': [{ 'b': { 'c': 3 } }] };

console.log(
  _.get(object, 'a[0].b.c'),           // => 3
  _.get(object, ['a', '0', 'b', 'c']), // => 3
  _.get(object, 'a.b.c'),              // => undefined 
  _.get(object, 'a.b.c', 'default')    // => 'default'
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>


Isso efetivamente verificará se essa chave, por mais profunda que seja, está definida e não emitirá um erro que poderá prejudicar o fluxo do seu programa se essa chave não estiver definida.

vsync
fonte
4

Embora isso não verifique necessariamente se existe uma chave, verifica a veracidade de um valor. Qual undefinede nullcair.

Boolean(obj.foo)

Essa solução funciona melhor para mim, porque eu uso o texto datilografado e o uso de seqüências de caracteres como essa 'foo' in objou obj.hasOwnProperty('foo') para verificar se uma chave existe ou não, não me fornece inteligência.

realappie
fonte
3

Se você deseja verificar qualquer chave em qualquer profundidade de um objeto e considerar os valores de falsey, considere esta linha para uma função de utilitário:

var keyExistsOn = (o, k) => k.split(".").reduce((a, c) => a.hasOwnProperty(c) ? a[c] || 1 : false, Object.assign({}, o)) === false ? false : true;

Resultados

var obj = {
    test: "",
    locals: {
        test: "",
        test2: false,
        test3: NaN,
        test4: 0,
        test5: undefined,
        auth: {
            user: "hw"
        }
    }
}

keyExistsOn(obj, "")
> false
keyExistsOn(obj, "locals.test")
> true
keyExistsOn(obj, "locals.test2")
> true
keyExistsOn(obj, "locals.test3")
> true
keyExistsOn(obj, "locals.test4")
> true
keyExistsOn(obj, "locals.test5")
> true
keyExistsOn(obj, "sdsdf")
false
keyExistsOn(obj, "sdsdf.rtsd")
false
keyExistsOn(obj, "sdsdf.234d")
false
keyExistsOn(obj, "2134.sdsdf.234d")
false
keyExistsOn(obj, "locals")
true
keyExistsOn(obj, "locals.")
false
keyExistsOn(obj, "locals.auth")
true
keyExistsOn(obj, "locals.autht")
false
keyExistsOn(obj, "locals.auth.")
false
keyExistsOn(obj, "locals.auth.user")
true
keyExistsOn(obj, "locals.auth.userr")
false
keyExistsOn(obj, "locals.auth.user.")
false
keyExistsOn(obj, "locals.auth.user")
true

Consulte também este pacote do NPM: https://www.npmjs.com/package/has-deep-value

Alex
fonte
3
const object1 = {
  a: 'something',
  b: 'something',
  c: 'something'
};

const key = 's';

// Object.keys(object1) will return array of the object keys ['a', 'b', 'c']

Object.keys(object1).indexOf(key) === -1 ? 'the key is not there' : 'yep the key is exist';
sarea
fonte
3

No mundo 'array', podemos olhar nos índices como algum tipo de chave. O que surpreende o inoperador (que é uma boa escolha para o objeto) também trabalha com matrizes. O valor retornado para a chave inexistente éundefined

let arr = ["a","b","c"]; // we have indexes: 0,1,2
delete arr[1];           // set 'empty' at index 1
arr.pop();               // remove last item

console.log(0 in arr,  arr[0]);
console.log(1 in arr,  arr[1]);
console.log(2 in arr,  arr[2]);

Kamil Kiełczewski
fonte
2

yourArray.indexOf (yourArrayKeyName)> -1

fruit = ['apple', 'grapes', 'banana']

fruit.indexOf('apple') > -1

verdade


fruit = ['apple', 'grapes', 'banana']

fruit.indexOf('apple1') > -1

falso

Anupam Maurya
fonte
0

Este exemplo pode demonstrar as diferenças entre maneiras diferentes. Espero que ajude você a escolher o caminho certo para suas necessidades:

// Lets create object `a` using create function `A`
function A(){};
A.prototype.onProtDef=2;
A.prototype.onProtUndef=undefined;
var a=new A();
a.ownProp = 3;
a.ownPropUndef = undefined;

// Let's try different methods:

a.onProtDef; // 2
a.onProtUndef; // undefined
a.ownProp; // 3
a.ownPropUndef; // undefined
a.whatEver; // undefined
a.valueOf; // ƒ valueOf() { [native code] }

a.hasOwnProperty('onProtDef'); // false
a.hasOwnProperty('onProtUndef'); // false
a.hasOwnProperty('ownProp'); // true
a.hasOwnProperty('ownPropUndef'); // true
a.hasOwnProperty('whatEver'); // false
a.hasOwnProperty('valueOf'); // false

'onProtDef' in a; // true
'onProtUndef' in a; // true
'ownProp' in a; // true
'ownPropUndef' in a; // true
'whatEver' in a; // false
'valueOf' in a; // true (on the prototype chain - Object.valueOf)

Object.keys(a); // ["ownProp", "ownPropUndef"]
Alexander
fonte
-1

Nova solução impressionante com a destruição do JavaScript :

let obj = {
    "key1": "value1",
    "key2": "value2",
    "key3": "value3",
};

let {key1, key2, key3, key4} = obj;

// key1 = "value1"
// key2 = "value2"
// key3 = "value3"
// key4 = undefined

// Can easily use `if` here on key4
if(!key4) { console.log("key not present"); } // Key not present

Verifique outro uso da destruição de JavaScript

NAVIN
fonte