Проверка, существует ли ключ в объекте JavaScript?


2973

Как проверить, существует ли определенный ключ в объекте или массиве JavaScript?

Если ключ не существует, и я пытаюсь получить к нему доступ, он вернет false? Или скинуть ошибку?


2
Все (почти все) в JavaScript является объектом или может быть приведено как единое целое. Именно здесь рождаются псевдоассоциативные массивы, как указывал @PatrickM.
Эндрю Ларссон

Этот тест jsben.ch/#/WqlIl дает вам обзор наиболее распространенных способов выполнения этой проверки.
EscapeNetscape

быстрый обходной путь, обычно я иду на property.key = property.key || 'some default value'всякий случай, если я хочу, чтобы этот ключ существовал с некоторой ценностью для него
RGLSV

Ответы:


4121

Проверка на неопределенность не является точным способом проверки существования ключа. Что если ключ существует, но значение действительно 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
Наличие свойства с заданным вручную значением undefined не имеет абсолютно никакого смысла. Это был бы оксюморон на самом деле.
Джоберт

259
Я убежден, что есть варианты использования для преднамеренного задания свойств неопределенными.
Атес Горал

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

7
Аналогичная проблема существует в PHP, где null == не существует: stackoverflow.com/q/418066/372654 и, к сожалению, null также используется там.
Халил Озгюр

80
@joebert То, что что-то бессмысленно, не означает, что вы не столкнетесь с этим в рабочем коде. Есть много библиотек, которые делают бессмысленные вещи.
Crashworks

298

быстрый ответ

Как проверить, существует ли определенный ключ в объекте или массиве JavaScript? Если ключ не существует, и я пытаюсь получить к нему доступ, он вернет false? Или скинуть ошибку?

Прямой доступ к отсутствующему свойству с использованием (ассоциативного) стиля массива или стиля объекта вернет неопределенную константу.

Медленный и надежный в операторе и hasOwnProperty метод

Как уже упоминалось здесь, у вас может быть объект со свойством, связанным с неопределенной константой.

 var bizzareObj = {valid_key:  undefined};

В этом случае вам придется использовать hasOwnProperty или в операторе , чтобы знать , если ключ действительно есть. Но, но по какой цене?

Итак, я говорю вам ...

in operator и 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

РЕДАКТИРОВАТЬ: Какова причина, чтобы присвоить свойству 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()метод.

РЕДАКТИРОВАТЬ: 12/04/2018 - НЕ ОТНОСИТЕЛЬНО больше

Как прокомментировали люди, современные версии движков Javascript (за исключением Firefox) изменили подход к свойствам доступа. Текущая реализация медленнее, чем предыдущая, для этого конкретного случая, но разница между ключом доступа и объектом незначительна.


1
Являются ли все эти методы приемлемыми во всех широко используемых браузерах, например, IE8 +?
Джастин

11
+1 для бенчмаркинга. Спасибо, это именно та информация, которую я надеялся найти. Определенно сильный аргумент для написания кода, который никогда не назначает или ожидает, что ключ будет содержать значение undefined .
TJ Комптон

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

3
Одна из причин , я установил бы неопределенными в хэш - значение, что я на самом деле хотел , чтобы удалить этот ключ свойства из хэш, но delete hash[key]это гораздо медленнее , чем hash[key] = undefined . Конечно, в этом случае для меня нет смысла нуждаться в inоператоре, но он действует как контрпример «мы всегда должны избегать установки значения в undefined».
Алан Там

1
Как упомянул @ HüseyinYağlı, если вы проверите ссылку jsperf , производительность значительно изменилась между различными методами для большинства браузеров, так как этот ответ был изначально написан. Firefox - один из немногих, у которого все еще есть значительное преимущество, используя методы массива или объекта, но для многих других браузеров различия незначительны.
Кевинмике

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
Вы должны использовать === вместо == при сравнении с undefined, иначе null будет сравниваться как undefined.
Мэтью Крамли

10
Или ваш ответ не совсем точен. Потому что в любом случае (и, конечно, это никогда не должно быть сделано) undefined не является специальным постоянным значением. На самом деле, это не зарезервированное ключевое слово, и вы можете перезаписать его, скажем, так 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?


Хороший вопрос, спасибо. :)
Лукас Соуза

29
"key" in obj

Вероятно, тестируются только значения атрибутов объекта, которые сильно отличаются от ключей массива


Этот код даст значение true также для ключа, который определен в прототипе Class: function A () {}; A.prototype.b = 2; var a = new A (); Тогда «б» в а это правда. Хотя a.hasOwnProperty ('b'), конечно, ложно.
Александр

24

Три способа проверить, присутствует ли свойство в объекте javascript:

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

Ссылка:

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


!! obj.theProperty завершается ошибкой, когда значение не определено. Пример:var a = {a : undefined, b : null}; !!a.a **will return false**
ARJUN

из обзора: !!obj.thePropertyэто не решение для проверки, если объект имеет свойство с именем theProperty. Сбой для любого значения свойства falsey,, undefinednull, numeric 0или NaN, и пустой строки""
traktor53

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метод? (если вы ищете значение, то есть)
Ник Ф

9

Ванила 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
Это не удастся для неисчислимых свойств объекта.
Сид

@ Сид Дай мне пример.
добрый пользователь

Ну вот. let joshua = {имя: 'Иисус Навин', адрес: 'Лондон'}; Object.defineProperty (joshua, 'isMarried', {value: true, enumerable: false}); console.log ('isMarried' в Object.keys (joshua))
Сид

Я применяю ваше решение на моем объекте. Разве это не должно быть правдой для первого выхода? 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

Возвращаемое значение как true подразумевает, что ключ существует в объекте.


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)

Это решение работает лучше всего для меня, потому что я использую машинописный текст, и такие строки, как таковые, 'foo' in objили obj.hasOwnProperty('foo')для проверки, существует ли ключ или нет, не предоставляют мне intellisense.


3

Если вы хотите проверить любой ключ на любой глубине объекта и учесть значения Falsey, рассмотрите эту строку для служебной функции:

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 Destructuring :

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.