Как проверить, есть ли у объекта свойство в JavaScript?

1189

Как проверить, имеет ли объект свойство в JavaScript?

Рассмотрим:

x = {'key': 1};
if ( x.hasOwnProperty('key') ) {
    //Do this
}

Это лучший способ сделать это?

  • 13
    Я написал тест jsperf со всеми ответами, чтобы узнать, какой из них самый быстрый: jsperf.com/dictionary-contains-key
  • 0
    ('propertyName' в объекте)? «собственность есть»: «собственность не существует»
Показать ещё 1 комментарий
Теги:

25 ответов

1255
Лучший ответ

Я действительно смущен ответами, которые были даны - большинство из них просто неверно. Конечно, вы можете иметь свойства объекта, имеющие undefined, null или false значения. Поэтому простое уменьшение проверки свойств на typeof this[property] или, что еще хуже, x.key даст вам полностью вводящие в заблуждение результаты.

Это зависит от того, что вы ищете. Если вы хотите узнать, физически ли объект содержит свойство (и он не идет откуда-то вверх по цепочке прототипов), тогда object.hasOwnProperty - это путь. Все современные браузеры поддерживают его. (В более ранних версиях Safari - 2.0.1 и старше отсутствовали. Но эти версии браузера редко используются.)

Если вы ищете, если объект имеет свойство на нем, которое является итерируемым (когда вы перейдете по свойствам объекта, оно появится), а затем выполните: prop in object даст вам желаемый эффект.

Так как использование hasOwnProperty, вероятно, то, что вы хотите, и учитывая, что вам может понадобиться резервный метод, я предлагаю вам следующее решение:

var obj = {
    a: undefined,
    b: null,
    c: false
};

// a, b, c all found
for ( var prop in obj ) {
    document.writeln( "Object1: " + prop );
}

function Class(){
    this.a = undefined;
    this.b = null;
    this.c = false;
}

Class.prototype = {
    a: undefined,
    b: true,
    c: true,
    d: true,
    e: true
};

var obj2 = new Class();

// a, b, c, d, e found
for ( var prop in obj2 ) {
    document.writeln( "Object2: " + prop );
}

function hasOwnProperty(obj, prop) {
    var proto = obj.__proto__ || obj.constructor.prototype;
    return (prop in obj) &&
        (!(prop in proto) || proto[prop] !== obj[prop]);
}

if ( Object.prototype.hasOwnProperty ) {
    var hasOwnProperty = function(obj, prop) {
        return obj.hasOwnProperty(prop);
    }
}

// a, b, c found in modern browsers
// b, c found in Safari 2.0.1 and older
for ( var prop in obj2 ) {
    if ( hasOwnProperty(obj2, prop) ) {
        document.writeln( "Object2 w/ hasOwn: " + prop );
    }
}

Вышеописанное решение для кросс-браузера hasOwnProperty с одной оговоркой: оно не может различать случаи, когда идентичное свойство находится в прототипе и экземпляре - оно просто предполагает, что оно исходит из Прототип. Вы можете изменить его, чтобы быть более снисходительным или строгим, исходя из вашей ситуации, но по крайней мере это должно быть более полезным.

  • 4
    @grantwparks Если вы создаете простой плагин-слайдер и хотите проверить наличие элемента параметров, то это может быть больше, чем нужно. Вы можете просто сделать что-то вроде var w = opts.w || 100; , Но если вы что-то делаете в библиотеке, вам, возможно, придется пойти немного дальше в некоторых частях.
  • 0
    @ kralco626: Да, в настоящее время я чувствую, что довольно безопасно использовать hasOwnProperty () - но для действительно безопасного кроссбраузерного решения, используйте John.
Показать ещё 6 комментариев
249

С Underscore.js или (еще лучше) lodash:

_.has(x, 'key');

Что вызывает Object.prototype.hasOwnProperty, но (a) короче, и (b) использует "безопасную ссылку на hasOwnProperty" (т.е. работает, даже если hasOwnProperty перезаписывается).

В частности, lodash определяет _.has как:

   function has(object, key) {
      return object ? hasOwnProperty.call(object, key) : false;
   }
   // hasOwnProperty = Object.prototype.hasOwnProperty
  • 41
    Я думаю, это потому, что «добавить эту библиотеку» редко является популярным решением, даже если вопрос касается сложных манипуляций с DOM, а ответ «иди используй jQuery».
  • 9
    Я понимаю вашу точку зрения, @sudowned, спасибо. Между прочим, если бы кто-то возражал против включения всей библиотеки lodash, можно было бы скомпилировать подкомпоненты или npm install lodash.has который предоставляет модуль npm только с функцией has которая при минимизации компилирует до 175 байт. Также lodash.has/index.js взглянуть на lodash.has/index.js чтобы увидеть, как работает очень популярная и lodash.has/index.js библиотека.
Показать ещё 8 комментариев
117

Примечание: в настоящее время в большинстве случаев устаревшие из-за строгого режима и hasOwnProperty. Правильное решение - использовать строгий режим и проверять наличие свойства с помощью obj.hasOwnProperty. Этот ответ предшествует обоим этим вещам, по крайней мере столь же широко реализованным (да, это то, что старый). В качестве исторической заметки сделайте следующее.


Имейте в виду, что undefined (к сожалению) не зарезервированное слово в JavaScript, если вы не используете строгий режим. Поэтому кто-то (кто-то другой, очевидно) мог бы получить великую идею о его пересмотре, нарушив ваш код.

Таким образом, более надежный метод заключается в следующем:

if (typeof(x.attribute) !== 'undefined')

С другой стороны, этот метод гораздо более подробен и медленнее.: -/

Общей альтернативой является обеспечение того, чтобы undefined фактически undefined, например. путем ввода кода в функцию, которая принимает дополнительный параметр, называемый undefined, который не передал значение. Чтобы убедиться, что он не передал значение, вы можете сразу вызвать его непосредственно, например:

(function (undefined) {
    … your code …
    if (x.attribute !== undefined)
        … mode code …
})();
  • 6
    Просто любопытно, поскольку void 0 определен для возврата канонического undefined , можно ли сделать x.attribute !== void 0 ?
  • 1
    Брайан: я не эксперт, но это, похоже, умный способ сделать все правильно.
Показать ещё 7 комментариев
96

Как насчет?

var x = {'key': 1};

if ('key' in x) {
    console.log('has');
}
  • 9
    Просто отметим, что он работает с «объектами» в узком смысле, поэтому он объявлен как {} или создан с использованием конструктора, он не принимает массивы или примитивы. Не то, чтобы ОП требовало этого, но некоторые другие ответы представляют более широкие методы (работа с массивами, строками и т. Д.)
  • 0
    @ РСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ спасибо за указание на это (принятый ответ не дает подробностей о том, почему следует использовать оператор in или нет. Также обратите внимание, что оператор in имеет отличную поддержку браузеров IE 5.5+, Chrome 1.0+, Firefox 1.0+, Safari 3.0+ stackoverflow.com/questions/2920765/…
Показать ещё 2 комментария
39
if (x.key !== undefined)

Armin Ronacher, кажется, уже избил меня до него, но:

Object.prototype.hasOwnProperty = function(property) {
    return this[property] !== undefined;
};

x = {'key': 1};

if (x.hasOwnProperty('key')) {
    alert('have key!');
}

if (!x.hasOwnProperty('bar')) {
    alert('no bar!');
}

Более безопасное, но более медленное решение как указано Конрадом Рудольфом и Armin Ronacher будет:

Object.prototype.hasOwnProperty = function(property) {
    return typeof this[property] !== 'undefined';
};
  • 1
    Я не думаю, что это достаточно хорошо. x.hasOwnProperty('toString') === true;
  • 0
    Не просить не согласиться, но понять. Есть ли точка, в которой x.hasOwnProperty будет возвращать что-либо, кроме логического true или false? Если нет, то код, как размещено, должен работать каждый раз. Я полагаю, может быть, если бы метод был переопределен, но тогда полагаться на результат никогда не будет надежным, если вы не знаете переопределяющий метод.
Показать ещё 2 комментария
33

Вы можете использовать оператор in чтобы проверить, существует ли свойство объекта:

x = {'key': 1};
alert("key" in x);

Вы также можете просмотреть все свойства объекта с помощью цикла for - in, а затем проверить наличие определенного свойства:

for (prop in x) {
    if (prop == "key") {
        //Do something
    }
}

Необходимо учитывать, является ли это свойство объекта перечислимым или нет, потому что неперечислимые свойства не будут отображаться for-in цикле for-in. Кроме того, если свойство enumerable скрывает неперечислимое свойство прототипа, оно не будет отображаться в Internet Explorer 8 и более ранних версиях.

Если вам нужен список всех свойств экземпляра, перечислимых или нет, вы можете использовать

Object.getOwnPropertyNames(x);

Это вернет массив имен всех свойств, которые существуют в объекте.

Наконец, вы можете использовать оператор typeof для прямой проверки типа данных свойства объекта:

if (typeof x.key == "undefined") {
    alert("undefined");
}

Если свойство не существует в объекте, оно вернет строку undefined. В противном случае он вернет соответствующий тип свойства. Тем не менее, обратите внимание, что это не всегда правильный способ проверки, имеет ли объект свойство или нет, потому что у вас может быть свойство, для которого установлено значение undefined, в этом случае использование typeof x.key все равно вернет true (даже если ключ все еще находится в объекте).

Обновление: Вы можете проверить, существует ли свойство, сравнивая с неопределенным свойством javascript

if (x.key === undefined) {
    alert("undefined");
}

Это должно работать, если ключ не был специально установлен на undefined для объекта x

  • 0
    Ваша часть обновления неверна. Пожалуйста, посмотрите здесь: jsfiddle.net/sbgg04yg
  • 0
    Обновлен, чтобы показать сценарии, в которых сравнение с неопределенным свойством JavaScript может завершиться ошибкой
25

Пусть прорежут некоторую путаницу здесь. Во-первых, позвольте упростить, предполагая, что hasOwnProperty уже существует; Это верно для подавляющего большинства современных браузеров.

hasOwnProperty возвращает true, если переданное ему имя атрибута было добавлено к объекту. Он полностью не зависит от фактического значения, назначенного ему, которое может быть точно undefined.

Следовательно:

var o = {}
o.x = undefined

var a = o.hasOwnProperty('x')  // a is true
var b = o.x === undefined // b is also true

Тем не мение:

var o = {}

var a = o.hasOwnProperty('x')  // a is now false
var b = o.x === undefined // b is still true

Проблема в том, что происходит, когда объект в цепочке прототипов имеет атрибут со значением undefined? hasOwnProperty будет ложным для него, и так будет !== undefined. Тем не менее, для for..in все еще перечислить его в перечислении.

Суть в том, что нет кросс-браузерного способа (поскольку Internet Explorer не предоставляет __prototype__), чтобы определить, что определенный идентификатор не был прикреплен к объекту или чему-либо в его цепочке прототипов.

17

Если вы ищете свойство, то "НЕТ". Вы хотите:

if ('prop' in obj) { }

В общем, вам не важно, связано ли свойство с прототипом или объектом.

Однако, поскольку вы использовали "ключ" в своем примере кода, похоже, что вы рассматриваете объект как хэш, и в этом случае ваш ответ будет иметь смысл. Все ключи хешей будут свойствами объекта, и вы избегаете дополнительных свойств, предоставленных прототипом.

Ответ Джона Ресига был очень всеобъемлющим, но я думал, что это не ясно. Особенно, когда использовать "prop" в obj ".

  • 1
    Обратите внимание, что оператор in имеет превосходную поддержку браузеров IE 5.5+, Chrome 1.0+, Firefox 1.0+, Safari 3.0+ stackoverflow.com/questions/2920765/…
  • 0
    Как указано в другом комментарии, касающемся использования оператора in : «он работает с« объектами »в узком смысле, поэтому он объявлен как {} или создан с помощью конструктора, он не принимает массивы или примитивы. Не то, что OP этого требовал, но некоторые другие ответы представляют более широкие методы (работа с массивами, строками и т. д.) »
Показать ещё 1 комментарий
12

Да это:) Я думаю, вы также можете сделать Object.prototype.hasOwnProperty.call(x, 'key'), который также должен работать, если x имеет свойство hasOwnProperty:)

Но это тесты для собственных свойств. Если вы хотите проверить, есть ли у него свойство, которое также может быть установлено, вы можете использовать typeof x.foo != 'undefined'.

12
if (typeof x.key != "undefined") {

}

Поскольку

if (x.key)

не работает, если x.key разрешается false (например, x.key = "").

10

Для тестирования простых объектов используйте:    if (obj[x] !== undefined)

Если вы не знаете, какой тип объекта он использует:    if (obj.hasOwnProperty(x))

Все остальные параметры медленнее..

Подробнее

Оценка производительности 100 000 000 циклов под Nodejs для 5 вариантов, предложенных другими здесь:

function hasKey1(k,o) { return (x in obj); }
function hasKey2(k,o) { return (obj[x]); }
function hasKey3(k,o) { return (obj[x] !== undefined); }
function hasKey4(k,o) { return (typeof(obj[x]) !== 'undefined'); }
function hasKey5(k,o) { return (obj.hasOwnProperty(x)); }

Оценка говорит нам, что, если мы специально не хотим проверять цепочку прототипов объекта, а также сам объект, мы не должны использовать общую форму: if (X in Obj)... . Это в 2-6 раз медленнее в зависимости от использование

hasKey1 execution time: 4s 510.427785ms
hasKey2 execution time: 0s 904.374806ms
hasKey3 execution time: 0s 760.336193ms
hasKey4 execution time: 0s 935.19901ms
hasKey5 execution time: 2s 148.189608ms

Нижняя строка, если ваш объект Obj не обязательно является простым объектом, и вы хотите избежать проверки цепи прототипа объекта и убедиться, что x принадлежит Obj напрямую, используйте "if (obj.hasOwnProperty(x))...".

В противном случае при использовании простого объекта и не беспокоясь о цепочке прототипов объекта, использование if (typeof(obj[x]) !== 'undefined')... является самым безопасным и быстрым способом.

Если вы используете простой объект в качестве хеш-таблицы и никогда не делаете ничего странного, я бы использовал if (obj[x])..., поскольку считаю его более читаемым.

Удачи.

10

Вы также можете использовать объект ES6 Reflect:

x = {'key': 1};
Reflect.has( x, 'key'); // returns true

Документацию по MDN для Reflect.has можно найти здесь.

Статический метод Reflect.has() работает как в операторе как функция.

  • 0
    Создайте красивую обертку, например:
7

ОК, похоже, что у меня был правильный ответ, если вы не хотите унаследованных свойств:

if (x.hasOwnProperty('key'))

Вот некоторые другие опции для включения унаследованных свойств:

if (x.key) // Quick and dirty, but it does the same thing as below.

if (x.key !== undefined)
  • 3
    Предупреждение x.hasOwnProperty ('key') может быть истинным, в то время как x.key! == undefined не является истинным.
  • 4
    Для var x = { key: false }; метод x.key был бы неправильным.
Показать ещё 1 комментарий
5

hasOwnProperty "может использоваться для определения того, имеет ли объект указанное свойство как прямое свойство этого объекта; в отличие от оператора, этот метод не проверяет цепочку прототипов объекта."

Так что, скорее всего, для того, что кажется по вашему вопросу, вы не хотите использовать hasOwnProperty, который определяет, существует ли свойство как прикрепленное непосредственно к самому объекту,

Если вы хотите определить, существует ли свойство в цепочке прототипов, которую вы хотите использовать в основном, например:

if( prop in object ){ // do something }

Надеюсь, это поможет.

  • 0
    Я получаю «Невозможно использовать оператор« in »для поиска« prop »в myObject»
3

Другим относительно простым способом является использование Object.keys. Это возвращает array, что означает, что вы получаете все возможности массива.

var noInfo = {};
var info = {something: 'data'};

Object.keys(noInfo).length //returns 0 or false
Object.keys(info).length //returns 1 or true

Хотя мы находимся в мире с отличной поддержкой браузера. Поскольку этот вопрос настолько старый, я думал, что добавлю следующее: Это безопасно использовать как JS v1.8.5

  • 0
    Правильно, но что, если вы хотите знать, есть ли у информации свойство с именем что-то другое? То, что думает, это то, что ищет OP.
  • 2
    Тогда вы бы сделали Object.keys(info).indexOf('someotherthing') !== -1
2

Не делайте этот object.hasOwnProperty(key)), это действительно плохо, потому что эти методы могут быть скрыты свойствами рассматриваемого объекта - рассмотрите { hasOwnProperty: false } - или объект может быть нулевым объектом (Object.create(null)).

Лучше всего сделать Object.prototype.hasOwnProperty.call(object, key) или:

const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope.
/* or */
import has from 'has'; // https://www.npmjs.com/package/has
// ...
console.log(has.call(object, key));
2

Существует метод "hasOwnProperty" существует на объекте, но его не рекомендуется напрямую обращаться к этому методу, потому что иногда объект имеет значение null или какое-либо свойство существует на объекте, например: { hasOwnProperty: false }

Таким образом, лучший способ:

// good
var obj = {"bar": "here bar desc"}
console.log(Object.prototype.hasOwnProperty.call(obj, "bar"));

// best
const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope.
console.log(has.call(obj, "bar"));
2

ECMA Script 6 решение с отражением. Создайте обертку наподобие:

/**
Gets an argument from array or object.
The possible outcome:
- If the key exists the value is returned.
- If no key exists the default value is returned.
- If no default value is specified an empty string is returned.
@param obj    The object or array to be searched.
@param key    The name of the property or key.
@param defVal Optional default version of the command-line parameter [default ""]
@return The default value in case of an error else the found parameter.
*/
function getSafeReflectArg( obj, key, defVal) {
   "use strict";
   var retVal = (typeof defVal === 'undefined' ? "" : defVal);
   if ( Reflect.has( obj, key) ) {
       return Reflect.get( obj, key);
   }
   return retVal;
}  // getSafeReflectArg
  • 0
    Это лучший способ сделать это, когда вы нацеливаетесь на> = ES6?
  • 1
    Imho, это самый короткий и самый простой ответ, но, возможно, не самый быстрый в исполняемом коде. Но скорость не проблема (больше).
2

С риском массивного downvoting, вот еще один вариант для конкретного случая.:)

Если вы хотите протестировать участника на объекте и хотите узнать, установлено ли оно для чего-то другого, кроме:

  • ''
  • ложь
  • NULL
  • undefined
  • 0 ...

то вы можете использовать:

var foo = {};
foo.bar = "Yes, this is a proper value!";
if (!!foo.bar) {
        // member is set, do something
}
1

Вам нужно использовать метод object.hasOwnProperty(property). Он возвращает true, если объект имеет свойство и false, если объект этого не делает.

1

Вы также можете использовать этот компонент многократного использования с открытым исходным кодом, который я написал под названием object-hasOwnProperty.

Пример:

hasOwnProperty({foo: 'bar'}, 'foo') // => true
hasOwnProperty({foo: 'bar'}, 'bar') // => false

Это довольно просто:

function hasOwnProperty(obj: {}, prop: string|number): boolean {
  return Object.prototype.hasOwnProperty.call(obj, prop);
};
0

Вы можете использовать следующее approaches-

var obj = {a:1}
console.log('a' in obj)               //1
console.log(obj.hasOwnProperty('a'))  //2
console.log(Boolean(obj.a))         //3

Разница между следующими подходами заключается в follows-

  1. При первом и третьем подходе мы ищем не только объект, но и его цепочку прототипов. Если объект не имеет свойства, но свойство присутствует в его цепочке прототипов, он собирается дать значение true.

 var obj = {
      a:2,
      __proto__ :{b:2}
    }

    console.log('b' in obj)
    console.log(Boolean(obj.b))
  1. 2-й подход будет проверять только свои свойства. Ex -

var obj = {
      a:2,
      __proto__ :{b:2}
    }

    console.log(obj.hasOwnProperty('b'))
  1. Разница между 1-м и 3-м заключается в том, что если есть свойство, значение которого не определено, 3-й подход даст значение false, а первый даст значение true.

var obj = {
      b : undefined
    }
    console.log(Boolean(obj.b))
    console.log('b' in obj);
0

Зачем слишком усложнять вещи, когда вы можете сделать:

var isProperty =  (objectname.keyname || "") ? true : false;

Просто и понятно в большинстве случаев...

  • 0
    Самым простым из них является var isProperty = !! objectname.keyname;
0

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

x = {'key': 1};
y = 'key';
x[y];
  • 0
    Чем это концептуально отличается от простого тестирования x ['key']? И чем это отличается от x.key? Кроме доступа к массиву, конечно ..
-1

Я использовал это. что очень помогло мне, если у вас есть объекты внутри объекта

if(typeof(obj["key"])=="string"){
    alert("property");
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню