Sprawdzanie, czy klucz istnieje w obiekcie JavaScript?

2965

Jak sprawdzić, czy określony klucz istnieje w obiekcie lub tablicy JavaScript?

Jeśli klucz nie istnieje i spróbuję uzyskać do niego dostęp, czy zwróci wartość false? Lub rzucić błąd?

Adam Ernst
źródło
2
Wszystko (prawie wszystko) w JavaScript jest obiektem lub może być rzutowane jako jeden. To tutaj rodzą się pseudo asocjacyjne tablice, jak wskazał @PatrickM.
Andrew Larsson,
Ten test porównawczy jsben.ch/#/WqlIl daje przegląd najczęstszych sposobów osiągnięcia tego sprawdzenia.
EscapeNetscape
szybkie obejście, zwykle property.key = property.key || 'some default value'
wybieram

Odpowiedzi:

4113

Sprawdzanie niezdefiniowanej nie jest dokładnym sposobem sprawdzenia, czy klucz istnieje. Co jeśli klucz istnieje, ale wartość jest rzeczywiście undefined?

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

Zamiast tego powinieneś użyć inoperatora:

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

Jeśli chcesz sprawdzić, czy klucz nie istnieje, pamiętaj o użyciu nawiasu:

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

Lub jeśli chcesz szczególnie przetestować właściwości instancji obiektu (a nie właściwości dziedziczone), użyj hasOwnProperty:

obj.hasOwnProperty("key") // true

Dla porównania wydajności między metodami, które są in, hasOwnPropertya kluczem jest undefined, zobacz ten wzorzec

Ates Goral
źródło
83
Posiadanie właściwości o ręcznie zdefiniowanej wartości niezdefiniowanej nie ma absolutnie żadnego sensu. To naprawdę byłby oksymoron.
Joebert
259
Jestem przekonany, że istnieją przypadki użycia, dla których właściwości celowo ustawiono na niezdefiniowane.
Ates Goral
168
Prawidłowy przypadek użycia: Gecko 1.9.1 [Firefox 3.5] nie ma właściwości window.onhashchange. Gecko 1.9.2 [Firefox 3.6] ma tę właściwość ustawioną na niezdefiniowaną (do czasu zmiany skrótu). Aby funkcja wykryła historię skrótów lub wersję przeglądarki, należy użyć window.hasOwnProperty („onhashchange”);
SamGoody,
7
Podobny problem istnieje w PHP, gdzie null == nieistniejący: stackoverflow.com/q/418066/372654 i niestety, null ma tam również zastosowanie.
Halil Özgür
80
@joebert To, że coś jest bzdurą, nie oznacza, że ​​nie spotkasz tego w kodzie produkcyjnym. Istnieje wiele bibliotek, które robią bezsensowne rzeczy.
Crashworks,
298

szybka odpowiedź

Jak sprawdzić, czy określony klucz istnieje w obiekcie lub tablicy JavaScript? Jeśli klucz nie istnieje i spróbuję uzyskać do niego dostęp, czy zwróci wartość false? Lub rzucić błąd?

Bezpośredni dostęp do brakującej właściwości za pomocą (asocjacyjnego) stylu tablicy lub stylu obiektu zwróci niezdefiniowaną stałą.

Powolne i niezawodne w operatora i hasOwnProperty Sposób

Jak już wspomniano tutaj, możesz mieć obiekt o właściwości powiązanej z „niezdefiniowaną” stałą.

 var bizzareObj = {valid_key:  undefined};

W takim przypadku trzeba będzie używać hasOwnProperty lub w operatora wiedzieć, czy klucz jest naprawdę istnieje. Ale, ale za jaką cenę?

więc mówię ci ...

w operator i hasOwnProperty są „metodami”, które wykorzystują mechanizm deskryptora właściwości w Javascript (podobny do odbicie Java w języku Java).

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

Typ deskryptora właściwości służy do wyjaśnienia manipulacji i weryfikacji nazwanych atrybutów właściwości. Wartości typu Deskryptor właściwości to rekordy złożone z nazwanych pól, w których nazwa każdego pola jest nazwą atrybutu, a jego wartość jest odpowiednią wartością atrybutu określoną w 8.6.1. Ponadto dowolne pole może być obecne lub nieobecne.

Z drugiej strony wywołanie metody obiektu lub klucza spowoduje użycie mechanizmu Javascript [[Get]]. To jest o wiele szybsze!

reper

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

Porównywanie dostępu klucza w JS.

Korzystanie z operatora
var result = "Impression" in array;

Wynik był

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

Wynik był

16,021,758 ±0.45% ops/sec     91% slower
Bezpośredni dostęp do elementów (styl nawiasów)
var result = array["Impression"] === undefined

Wynik był

168,270,439 ±0.13 ops/sec     0.02% slower 
Bezpośredni dostęp do elementów (styl obiektu)
var result = array.Impression  === undefined;

Wynik był

168,303,172 ±0.20%     fastest

EDYCJA: Jaki jest powód przypisania do właściwości undefinedwartości?

To pytanie mnie zastanawia. W Javascripcie istnieją co najmniej dwa odwołania do nieobecnych obiektów, aby uniknąć takich problemów: nulli undefined.

nulljest pierwotną wartością, która reprezentuje celowy brak jakiejkolwiek wartości obiektu, lub w skrócie potwierdzony brak wartości. Z drugiej strony, undefinedwartość nieznana (nie zdefiniowana). Jeśli istnieje właściwość, która zostanie użyta później z odpowiednią wartością, rozważ użycie nullodwołania zamiast, undefinedponieważ w początkowej chwili potwierdzono, że właściwość nie ma wartości.

Porównać:

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[].

Doradzać

Unikaj obiektów z undefinedwartościami. Sprawdź bezpośrednio, gdy tylko jest to możliwe, i użyj, nullaby zainicjować wartości właściwości. W przeciwnym razie użyj powolnego inoperatora lub hasOwnProperty()metody.

EDYCJA: 12.04.2018 - NIE JEST ODPOWIEDNIE

Jak ludzie skomentowali, nowoczesne wersje silników JavaScript (z wyjątkiem Firefoxa) zmieniły podejście do właściwości dostępu. Bieżąca implementacja jest wolniejsza niż poprzednia w tym konkretnym przypadku, ale różnice między kluczem dostępu a obiektem są pomijalne.

rdllopes
źródło
1
Czy wszystkie te metody są dopuszczalne we wszystkich powszechnie używanych przeglądarkach, np. IE8 +?
Justin
11
+1 za testy porównawcze. Dziękuję, właśnie takie informacje chciałem znaleźć. Zdecydowanie silny argument do napisania kodu, który nigdy nie przypisuje ani nie oczekuje, że klucz będzie zawierał niezdefiniowaną wartość .
TJ Compton,
Byłem ciekawy, jak porównała się Underscore.js (), więc dodałem ją do jsperf ( wersja 11 ). Okazuje się, że jest w wolnej grupie wraz z in i hasOwnProperty ().
mpoisot,
3
Jednym z powodów, dla których ustawiłem wartość niezdefiniowaną na wartość skrótu jest to, że tak naprawdę chciałem usunąć ten klucz właściwości z skrótu, ale delete hash[key]jest on znacznie wolniejszy niż hash[key] = undefined . Oczywiście w tym przypadku nie ma potrzeby potrzebować inoperatora, ale działa on jako kontrprzykład na „zawsze należy unikać ustawiania wartości na niezdefiniowaną”.
Alan Tam
1
Jak wspomniano @ HüseyinYağlı, jeśli sprawdzisz link jsperf , wydajność znacznie się zmieniła między różnymi metodami dla większości przeglądarek, odkąd ta odpowiedź została napisana. Firefox jest jedną z niewielu, która nadal ma znaczącą przewagę przy użyciu metod tablicowych lub obiektowych, ale w wielu innych przeglądarkach różnice są znikome.
kevinmicke
144

Wróci undefined.

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

undefinedjest specjalną stałą wartością. Możesz więc powiedzieć np

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

Jest to prawdopodobnie najlepszy sposób na sprawdzenie brakujących kluczy. Jednak, jak wskazano w komentarzu poniżej, teoretycznie możliwe jest, że chcesz mieć rzeczywistą wartość undefined. Nigdy nie musiałem tego robić i nie mogę wymyślić żadnego powodu, dla którego kiedykolwiek bym tego chciał, ale ze względu na kompletność możesz użyć inoperatora

// this works even if you have {"goodbye": undefined}
if( "goodbye" in aa ) {
    // do something
}
Eli Courtwright
źródło
8
Co jeśli klucz istnieje, ale wartość jest faktycznie niezdefiniowana?
Ates Goral
13
Powinieneś użyć === zamiast == przy porównywaniu z niezdefiniowanym, w przeciwnym razie null porówna się z niezdefiniowanym.
Matthew Crumley,
10
Eli twoja odpowiedź nie jest całkowicie dokładna. Ponieważ w każdym razie (i oczywiście nie należy tego nigdy robić) niezdefiniowana nie jest specjalną wartością stałą. W rzeczywistości nie jest to zastrzeżone słowo kluczowe i można je zastąpić, powiedzmy na przykład, że var undefined = 42;. Podczas testowania niezdefiniowanych rekwizytów należy zawsze używać ((typeof variable) === "undefined").
ssice
1
@ssice undefinednie jest własnością do zapisu zgodnie ze specyfikacją ecma-international.org/ecma-262/5.1/#sec-15.1.1.3
therealrootuser
1
We wcześniejszych wersjach JavaScript „niezdefiniowane” i „NaN” były zmiennymi, które można było przedefiniować lub przypisać innym wartościom . To było złe. Zostało to naprawione w ECMAScript 5.
jkdev
29
"key" in obj

Prawdopodobnie testuje tylko wartości atrybutów obiektu, które bardzo różnią się od kluczy tablicy

użytkownik2320522
źródło
Ten kod da także prawdę dla klucza zdefiniowanego w prototypie klasy: funkcja A () {}; A.prototype.b = 2; var a = new A (); Zatem „b” w a jest prawdą. Chociaż a.hasOwnProperty („b”) jest oczywiście fałszywe.
Alexander
24

Trzy sposoby sprawdzenia, czy właściwość jest obecna w obiekcie javascript:

  1. !! obj.theProperty
    Konwertuje wartość na bool. zwraca PRAWDA dla wszystkich oprócz wartości „fałsz”
  2. „theProperty” w obj Zwróci wartość
    true, jeśli właściwość istnieje, bez względu na jej wartość (nawet pusta)
  3. obj.hasOwnProperty ('theProperty')
    Nie sprawdza łańcucha prototypów. (ponieważ wszystkie obiekty mają metodę „toString”, 1 i 2 zwrócą na niej wartość true, a 3 może zwrócić na niej wartość false).

Odniesienie:

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

Lavi Avigdor
źródło
!! obj.theProperty kończy się niepowodzeniem, gdy wartość jest niezdefiniowana. Np .:var a = {a : undefined, b : null}; !!a.a **will return false**
ARJUN
15

Jeśli używasz biblioteki underscore.js, operacje na obiektach / tablicach stają się proste.

W twoim przypadku można zastosować metodę _. Przykład:

yourArray = {age: "10"}

_.has(yourArray, "age")

zwraca true

Ale,

_.has(yourArray, "invalidKey")

zwraca false

vatsal
źródło
15

Odpowiedź:

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

Wyjaśnienie:

inOperator sprawdzi, czy klucz istnieje w obiekcie. Jeśli sprawdziłeś, czy wartość była niezdefiniowana: if (myObj["key"] === 'undefined')możesz napotkać problemy, ponieważ w obiekcie może istnieć klucz z undefinedwartością.

Z tego powodu dużo lepszą praktyką jest najpierw użycie inoperatora, a następnie porównanie wartości znajdującej się w kluczu, gdy już wiesz, że on istnieje.

Webeng
źródło
12

Oto funkcja pomocnika, którą uważam za całkiem przydatną

To keyExists(key, search)może być używany do łatwo odszukać klucz wewnątrz obiektów lub tablic!

Po prostu przekaż mu klucz, który chcesz znaleźć, i wyszukaj obiekt obj (obiekt lub tablicę), w którym chcesz go znaleźć.

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

Jest dość niezawodny i działa dobrze w różnych przeglądarkach.

jaredwilli
źródło
6
Wydaje się to nieco zagmatwane: po pierwsze, podczas przeszukiwania tablicy ta metoda sprawdza wartość , a nie klucz. Po drugie, po co iterować po takiej tablicy, skoro można skorzystać z wbudowanej Array.indexOfmetody? (to znaczy jeśli szukasz wartości)
Nick F
9

vanila js

yourObjName.hasOwnProperty(key) : true ? false;

Jeśli chcesz sprawdzić, czy obiekt ma co najmniej jedną właściwość w es2015

Object.keys(yourObjName).length : true ? false
Hajji Tarik
źródło
7

Rozwiązanie ES6

za pomocą Array#somei Object.keys. Zwróci wartość true, jeśli dany klucz istnieje w obiekcie, lub false, jeśli nie istnieje.

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');

Przykład jednowierszowy.

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

miły użytkownik
źródło
1
Nie powiedzie się w przypadku właściwości obiektu niepoliczalnych.
Sid
@Sid Podaj mi przykład.
miły użytkownik
Proszę bardzo. let Joshua = {name: 'Joshua', adres: 'London'}; Object.defineProperty (joshua, 'isMarried', {value: true, enumerable: false}); console.log ('isMarried' w Object.keys (joshua))
Sid
Stosuję twoje rozwiązanie na moim obiekcie. Czy nie powinno to dawać prawdy dla pierwszego wyjścia? console.log (Object.keys (joshua) .some (v => v == 'isMarried')); console.log (joshua.isMarried);
Sid
1
Przepraszam, ale czy sprawdziłeś wynik instrukcji drugiej konsoli? Object.defineProperty jest równoważny z ustawieniem właściwości za pomocą notacji kropkowej.
Sid
6

Możemy użyć - hasOwnProperty.call(obj, key);

Sposób underscore.js -

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

_.has = function(obj, key) {
  return hasOwnProperty.call(obj, key);
};
Mohan Dere
źródło
5

Najłatwiejszym sposobem sprawdzenia jest

"key" in object

na przykład:

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

Zwracana wartość jako prawda oznacza, że ​​klucz istnieje w obiekcie.

shekhardtu
źródło
4

Dla tych, którzy wzięli lodashudział w projekcie:
Istnieje metoda lodash _.get , która próbuje uzyskać „głębokie” klucze:

Pobiera wartość na ścieżkę obiektu. Jeśli rozstrzygnięta wartość nie jest zdefiniowana, wartość defaultValue jest zwracana w jej miejsce.

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>


To skutecznie sprawdzi, czy ten klucz, jakkolwiek głęboki , jest zdefiniowany i nie wyrzuci błędu, który mógłby zaszkodzić przepływowi twojego programu, jeśli ten klucz nie zostanie zdefiniowany.

vsync
źródło
4

Chociaż nie musi to sprawdzać, czy klucz istnieje, sprawdza prawdziwość wartości. Które undefinedi nullnależą do.

Boolean(obj.foo)

To rozwiązanie działa najlepiej dla mnie, ponieważ używam maszynopisu, a użycie takich ciągów znaków 'foo' in objlub obj.hasOwnProperty('foo') sprawdzenie, czy klucz istnieje, czy nie, nie zapewnia mi inteligencji.

realappie
źródło
3

Jeśli chcesz sprawdzić dowolny klucz na dowolnej głębokości obiektu i uwzględnić wartości falsey, rozważ ten wiersz funkcji funkcji:

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

Wyniki

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

Zobacz także ten pakiet NPM: https://www.npmjs.com/package/has-deep-value

Alex
źródło
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
źródło
3

W świecie „tablicowym” indeksy możemy traktować jak pewien rodzaj kluczy. Co zaskakujące, inoperator (który jest dobrym wyborem dla obiektu) działa również z tablicami. Zwrócona wartość nieistniejącego klucza toundefined

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
źródło
2

yourArray.indexOf (yourArrayKeyName)> -1

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

fruit.indexOf('apple') > -1

prawdziwe


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

fruit.indexOf('apple1') > -1

fałszywe

Anupam Maurya
źródło
0

Te przykłady mogą wykazać różnice między różnymi sposobami. Mam nadzieję, że pomoże Ci wybrać odpowiedni dla swoich potrzeb:

// 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
źródło
-1

Nowe niesamowite rozwiązanie z JavaScript Destrukturyzacją :

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

Sprawdź inne użycie JavaScript Destrukturyzacja

NAVIN
źródło