Как проверить, есть ли у объекта свойство в JavaScript? - PullRequest
1316 голосов
/ 25 сентября 2008

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

Рассмотрим:

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

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

Ответы [ 24 ]

1305 голосов
/ 26 сентября 2008

Я действительно смущен ответами, которые были даны - большинство из них просто неверны. Конечно, у вас могут быть свойства объекта с неопределенными, нулевыми или ложными значениями. Так что простое уменьшение проверки свойства до 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 с одним предупреждением: невозможно различить случаи, когда идентичное свойство находится в прототипе, и в экземпляре - оно просто предполагает, что оно исходит от Прототип. Вы можете изменить его на более снисходительный или строгий, исходя из вашей ситуации, но, по крайней мере, это должно быть более полезным.

262 голосов
/ 03 июля 2012

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

_.has(x, 'key');

Который вызывает Object.prototype.hasOwnProperty, но (а) короче набирает текст и (б) использует «безопасную ссылку на hasOwnProperty» (т. Е. Работает, даже если hasOwnProperty перезаписан).

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

   function has(object, key) {
      return object ? hasOwnProperty.call(object, key) : false;
   }
   // hasOwnProperty = Object.prototype.hasOwnProperty
116 голосов
/ 25 сентября 2008

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


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

Следовательно, более надежный метод:

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

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

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

(function (undefined) {
    … your code …
    if (x.attribute !== undefined)
        … mode code …
})();
110 голосов
/ 02 февраля 2013

А как же?

var x = {'key': 1};

if ('key' in x) {
    console.log('has');
}
45 голосов
/ 25 сентября 2008
if (x.key !== undefined)

Армин Ронахер , кажется, уже победил меня в этом , но:

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

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

Object.prototype.hasOwnProperty = function(property) {
    return typeof this[property] !== 'undefined';
};
35 голосов
/ 30 марта 2014

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

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

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

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

Необходимо учитывать, является ли это свойство объекта перечислимым или нет, потому что неперечислимые свойства не будут отображаться в цикле for-in. Кроме того, если перечисляемое свойство скрывает не перечисляемое свойство прототипа, оно не будет отображаться в 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

27 голосов
/ 26 сентября 2008

Давайте рассмотрим здесь некоторую путаницу. Во-первых, давайте упростим, предположив, что 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__), чтобы определить, что определенный идентификатор не был прикреплен к объекту или чему-либо в его цепочке прототипов.

18 голосов
/ 21 мая 2013

Если вы ищете недвижимость, тогда «НЕТ». Вы хотите:

if ('prop' in obj) { }

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

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

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

14 голосов
/ 25 сентября 2008

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

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

13 голосов
/ 25 сентября 2008
if (typeof x.key != "undefined") {

}

Поскольку

if (x.key)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...