Перевірка наявності ключа в об’єкті JavaScript?


2965

Як перевірити, чи існує певний ключ в об’єкті або масиві JavaScript?

Якщо ключ не існує, і я намагаюся отримати доступ до нього, чи повернеться він помилковим? Або кинути помилку?


2
Все (майже все) в JavaScript є Об'єктом або може бути передано як одне ціле. Тут народжуються псевдоасоціативні масиви так, як вказував @PatrickM.
Ендрю Ларссон

цей орієнтир jsben.ch/#/WqlIl дає вам огляд найбільш поширених способів досягнення цієї перевірки.
EscapeNetscape

швидке вирішення, як правило, я property.key = property.key || 'some default value'
шукаю

Відповіді:


4115

Перевірка на невизначеність не є точним способом перевірити наявність ключа. Що робити, якщо ключ існує, але значення є насправді undefined?

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

Натомість слід використовувати inоператор:

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

Якщо ви хочете перевірити, чи не існує ключа, не забудьте скористатися дужками:

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

Або, якщо ви хочете особливо перевірити властивості об’єкта об'єкта (а не успадковані властивості), використовуйте hasOwnProperty:

obj.hasOwnProperty("key") // true

Для порівняння продуктивності між методами, які in, hasOwnPropertyі клавіша undefined, побачити цей тест


83
Мати властивість із визначеним вручну значенням невизначеного значення абсолютно не має сенсу. Це був би дійсно оксиморон.
joebert

259
Я переконаний, що є випадки використання для властивостей, навмисно встановлених як невизначені.
Атес Горал

168
Дійсний випадок використання: Gecko 1.9.1 [Firefox 3.5] не має властивості window.onhashchange. Gecko 1.9.2 [Firefox 3.6] має цю властивість не визначеною (поки хеш не зміниться). Щоб ознайомити історію хешу чи версію браузера, потрібно використовувати window.hasOwnProperty ("onhashchange");
SamGoody

7
Аналогічна проблема існує і в PHP, де null == не існує: stackoverflow.com/q/418066/372654, і, на жаль, і null має там своє використання.
Halil Özgür

80
@joebert Тільки тому, що щось є дурницею, не означає, що ви не зіткнетесь із цим у виробничому коді. Є багато бібліотек, які роблять безглузді речі.
Crashworks

298

швидка відповідь

Як перевірити, чи існує певний ключ в об’єкті або масиві JavaScript? Якщо ключ не існує, і я спробую отримати доступ до нього, чи повернеться він помилковим? Або кинути помилку?

Доступ безпосередньо до відсутньої властивості за допомогою (асоціативного) стилю масиву чи стилю об’єкта поверне невизначену константу.

Повільний і надійний в операторі та методі hasOwnProperty

Як люди вже згадували тут, у вас може бути об’єкт із властивістю, пов'язаною з "невизначеною" константою.

 var bizzareObj = {valid_key:  undefined};

У такому випадку вам доведеться використовувати hasOwnProperty або в оператора, щоб знати, чи ключ дійсно є. Але, але якою ціною?

так, я вам кажу ...

в операторі та hasOwnProperty - це "методи", які використовують механізм Дескриптора властивостей у Javascript (подібний до відображення Java в мові Java).

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

Тип Дескриптора властивостей використовується для пояснення маніпулювання та переробки названих атрибутів властивості. Значення типу "Дескриптор властивості" - це записи, що складаються з іменованих полів, де ім'я кожного поля є ім'ям атрибута, а його значення - відповідним значенням атрибута, як зазначено в 8.6.1. Крім того, будь-яке поле може бути присутнім або відсутнім.

З іншого боку, для виклику об'єктного методу чи ключа використовується механізм Javascript [[Get]]. Це набагато швидше!

орієнтир

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

Порівняння доступу ключів у JS.

Використання в операторі
var result = "Impression" in array;

Результат був

12,931,832 ±0.21% ops/sec      92% slower 
Використання hasOwnProperty
var result = array.hasOwnProperty("Impression")

Результат був

16,021,758 ±0.45% ops/sec     91% slower
Доступ до елементів безпосередньо (стиль дужок)
var result = array["Impression"] === undefined

Результат був

168,270,439 ±0.13 ops/sec     0.02% slower 
Доступ до елементів безпосередньо (стиль об'єкта)
var result = array.Impression  === undefined;

Результат був

168,303,172 ±0.20%     fastest

EDIT: Яка причина присвоїти властивості undefinedзначення?

Це питання спантеличує мене. У Javascript є щонайменше дві посилання на відсутні об'єкти, щоб уникнути таких проблем: nullіundefined .

null- це примітивне значення, яке являє собою навмисну ​​відсутність будь-якого об'єктного значення, або, стисло кажучи, підтверджену відсутність значення. З іншого боку, undefinedневідоме значення (не визначено). Якщо є властивість, яка буде використана пізніше з належним значенням, розгляньте nullпосилання на використання замість того, undefinedщо в початковий момент підтверджено, що властивість не має значення.

Порівняйте:

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

Порадьте

Уникайте об'єктів зі undefinedзначеннями. Перевірте безпосередньо, коли можливо, і використовуйте nullдля ініціалізації значень властивостей. В іншому випадку використовуйте повільний inоператор або hasOwnProperty()метод.

РЕДАКЦІЯ: 04.12.2018 - НЕ ВІДПОВІДАЙТЕ БІЛЬШЕ

Як коментують люди, сучасні версії двигунів Javascript (за винятком firefox) змінили підхід до властивостей доступу. Поточна реалізація проходить повільніше, ніж попередня для цього конкретного випадку, але різницю між ключем доступу та об'єктом нехтувати.


1
Чи прийнятні всі ці методи у всіх широко використовуваних браузерах, наприклад, IE8 +?
Джастін

11
+1 для тестування. Дякую, це саме та інформація, яку я сподівався знайти. Однозначно вагомий аргумент для написання коду, який ніколи не призначає або очікує, що ключ містить значення не визначеного .
TJ Compton

Мені було цікаво, як порівнюється () порівняння Underscore.js, тому я додав його до jsperf ( версія 11 ). Виявляється, він знаходиться в повільній групі разом з in і hasOwnProperty ().
mpoisot

3
Однією з причин, яку я встановив би невизначеним значенням хешу, є те, що я насправді хотів видалити цей ключ властивості з хешу, але delete hash[key]це набагато повільніше, ніж hash[key] = undefined . Звичайно, в цьому випадку для мене немає сенсу потребувати inоператора, але він виступає як контрприклад "ми завжди повинні уникати встановлення значення для невизначеного".
Алан Там

1
Як зазначав @ HüseyinYağlı, якщо перевірити посилання jsperf , продуктивність значно змінилася між різними методами для більшості браузерів, оскільки ця відповідь була написана спочатку. Firefox - одна з небагатьох, яка все ще має значну перевагу у використанні масиву чи об’єктних методів, але для багатьох інших браузерів відмінності незначні.
kevinmicke

144

Це повернеться undefined.

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

undefinedє особливим постійним значенням. Так можна сказати, наприклад

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

Це, мабуть, найкращий спосіб перевірити відсутні ключі. Однак, як зазначено в коментарі нижче, теоретично можливо, що ви хочете мати фактичне значення undefined. Мені ніколи не потрібно було це робити, і я не можу придумати причину, яку я хотів би коли-небудь, але просто для повноти ви можете використовувати inоператора

// this works even if you have {"goodbye": undefined}
if( "goodbye" in aa ) {
    // do something
}

8
Що робити, якщо ключ існує, але значення фактично не визначене?
Атес Горал

13
Ви повинні використовувати === замість == при порівнянні з невизначеним, інакше null буде порівняно з рівнем undefined.
Меттью Крамлі

10
Елі ваша відповідь не зовсім точна. Тому що все одно (і звичайно цього ніколи не слід робити) невизначене не є особливим постійним значенням. Насправді це не зарезервоване ключове слово, і ви можете його перезаписати, скажімо, наприклад, що var undefined = 42;. Під час тестування невизначених реквізитів завжди слід використовувати ((typeof variable) === "undefined").
ssice

1
@ssice undefinedтакож не буде перезаписано властивість згідно специфікації ecma-international.org/ecma-262/5.1/#sec-15.1.1.3
therealrootuser

1
У попередніх версіях JavaScript "undefined" і "NaN" були змінними змінними, яким можна було переосмислити або призначити інші значення . Це було погано. Це було зафіксовано в ECMAScript 5.
jkdev

32

Прийнятий відповідь відноситься до об'єкту . Обережно використовуйте inоператор у масиві для пошуку даних замість ключів:

("true" in ["true", "false"])
// -> false (Because the keys of the above Array are actually 0 and 1)

Для тестування наявних елементів у масиві: найкращий спосіб виявити, чи є елемент у масиві JavaScript?


Добрий момент, дякую. :)
Lucas Sousa

29
"key" in obj

Ймовірно, тестується лише значення атрибутів об'єкта, які сильно відрізняються від ключів масиву


Цей код відповідає дійсності також для ключа, визначеного в прототипі класу: функція A () {}; A.prototype.b = 2; var a = new A (); Тоді 'b' в a є істинним. Хоча a.hasOwnProperty ('b'), звичайно, помилковий.
Олександр

24

Три способи перевірити наявність властивості в об’єкті javascript:

  1. !! obj.theProperty
    перетворить значення в bool. повертає TRUE для всіх, окрім значення 'false'
  2. 'theProperty' в obj
    повернеться true, якщо властивість існує, незалежно від її значення (навіть порожнього)
  3. obj.hasOwnProperty ('theProperty')
    Не перевіряє ланцюжок прототипу. (оскільки всі об'єкти мають метод "toString", 1 і 2 повернуть на ньому істину, а 3 можуть повернути помилкове.)

Довідка:

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


!! obj.theProperty виходить з ладу, коли значення не визначене. Напр .:var a = {a : undefined, b : null}; !!a.a **will return false**
ARJUN

15

Якщо ви використовуєте бібліотеку underscore.js, то операції з об'єктом / масивом стають простими.

У вашому випадку можна використовувати метод _.has. Приклад:

yourArray = {age: "10"}

_.has(yourArray, "age")

повертає правду

Але,

_.has(yourArray, "invalidKey")

повертає помилкове


15

Відповідь:

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

Пояснення:

inОператор буде перевіряти , якщо ключ існує в об'єкті. Якщо ви перевірили, чи не визначено значення:, if (myObj["key"] === 'undefined')ви можете зіткнутися з проблемами, оскільки у вашому об'єкті зі undefinedзначенням може бути ключ .

З цієї причини набагато кращою практикою є спочатку використовувати inоператор, а потім порівняти значення, яке знаходиться всередині ключа, як тільки ви вже знаєте, що воно існує.


12

Ось помічна функція, яку я вважаю досить корисною

Це keyExists(key, search)можна використовувати для легкого пошуку ключа в об'єктах або масивах!

Просто передайте йому ключ, який ви хочете знайти, і шукайте obj (об’єкт або масив), в якому ви хочете його знайти.

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

Це було досить надійно і працює добре крос-браузер.


6
Це здається дещо заплутаним: по-перше, при пошуку масиву цей метод перевіряє значення , а не ключ. По-друге, навіщо повторювати такий масив, коли ви можете використовувати вбудований Array.indexOfметод? (якщо ви шукаєте значення, тобто)
Nick F

9

vanila js

yourObjName.hasOwnProperty(key) : true ? false;

Якщо ви хочете перевірити, чи має об’єкт принаймні одне властивість у es2015

Object.keys(yourObjName).length : true ? false

7

Рішення ES6

за допомогою Array#someта Object.keys. Він повернеться true, якщо вказаний ключ існує в об'єкті, або false, якщо його немає.

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

Приклад однолінійного.

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


1
Він не зможе отримати безлічі властивості об'єкта.
Сід

@Sid Наведіть мені приклад.
доброго користувача

Ось ви йдете. нехай joshua = {ім'я: 'Джошуа', адреса: 'Лондон'}; Object.defineProperty (joshua, 'isMarried', {value: true, enumerable: false}); console.log ( 'isMarried' в Object.keys (Joshua))
Sid

Я застосовую ваше рішення на моєму об’єкті. Чи не повинно це бути правдою для першого виходу? console.log (Object.keys (joshua) .some (v => v == 'isMarried')); console.log (joshua.isMarried);
Сід

1
Вибачте, але ви перевірили вихід заяви другої консолі? Object.defineProperty еквівалентно встановленню властивості за допомогою крапкових позначень.
Сід

6

Ми можемо використовувати - hasOwnProperty.call(obj, key);

Спосіб underscore.js -

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

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

5

Найпростіший спосіб перевірити це

"key" in object

наприклад:

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

Повернене значення як істинне означає, що ключ існує в об'єкті.


4

Для тих, хто lodashвключив у свій проект:
Існує метод lodash _.get, який намагається отримати «глибокі» ключі:

Отримує значення на шляху об'єкта. Якщо вирішене значення не визначене, на його місце повертається defaultValue.

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>


Це ефективно перевірить, чи визначений цей ключ, наскільки глибокий , і не призведе до помилки, яка може зашкодити потоку вашої програми, якщо цей ключ не визначений.


4

Хоча це не обов'язково перевіряє, чи існує ключ, він перевіряє правдивість значення. Які undefinedі nullпідпадають.

Boolean(obj.foo)

Це рішення найкраще працює для мене, тому що я використовую typecript, і використовуючи рядки, подібні до цього, 'foo' in objабо obj.hasOwnProperty('foo') перевіряти, чи існує ключ чи ні, це не дає мені інтелігенції.


3

Якщо ви хочете перевірити наявність будь-якого ключа на будь-якій глибині об'єкта і врахувати значення фальси, розгляньте цей рядок для функції корисності:

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

Результати

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

Також дивіться цей пакет NPM: https://www.npmjs.com/package/has-deep-value


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

3

У світі "масиву" ми можемо дивитись на індекси як на деякі клавіші. Що дивно, що inоператор (що є хорошим вибором для об'єкта), також працює з масивами. Повертається значення для неіснуючого ключа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]);


2

yourArray.indexOf (yourArrayKeyName)> -1

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

fruit.indexOf('apple') > -1

правда


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

fruit.indexOf('apple1') > -1

помилковий


0

Цей приклад може продемонструвати відмінності між різними способами. Сподіваємось, це допоможе вам вибрати потрібний для ваших потреб:

// 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"]

-1

Нове дивовижне рішення з руйнуванням 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

Перевірте інше використання JavaScript Destructuring

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.