Обнаружение объектов JavaScript: синтаксис точки и ключевое слово in - PullRequest
62 голосов
/ 24 августа 2011

Я видел два способа определения того, реализует ли UA конкретное свойство JS: if(object.property) и if('property' in object).

Я хотел бы услышать мнения о том, что лучше, а главное, почему. Одно однозначно лучше другого? Есть ли что-то большее, чем просто эти два способа обнаружения свойств объекта? Пожалуйста, расскажите о поддержке браузера, подводных камнях, скорости выполнения и т. П., А не об эстетике.

Редактировать: Читателям рекомендуется запускать тесты по адресу jsperf.com / object-Detection

Ответы [ 5 ]

115 голосов
/ 24 августа 2011
  • if(object.property)

    потерпит неудачу в тех случаях, когда он не установлен (что вам нужно), и в тех случаях, когда ему было задано какое-то ложное значение, например, undefined, null, 0 и т. Д. (Это не то, что вы хотите).

    var object = {property: 0};
    if(object.isNotSet) { ... } // will not run
    if(object.property) { ... } // will not run
    
  • if('property' in object)

    немного лучше, так как он на самом деле вернет, обладает ли объект действительно свойством, а не просто посмотрев на его значение.

    var object = {property: 0};
    if('property' in object) { ... } // will run
    if('toString' in object) { ... } // will also run; from prototype
    
  • if(object.hasOwnProperty('property'))

    еще лучше, поскольку это позволит вам различать свойства экземпляра и свойства прототипа.

    var object = {property: 0};
    if(object.hasOwnProperty('property')) { ... } // will run
    if(object.hasOwnProperty('toString')) { ... } // will not run
    

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


Редактировать: Вы также можете сделать общую функцию для проверки существования свойства, передавая что-либо (даже вещи, которые не являются объектами) как объект, подобный этому:

function has(obj, prop) {
    return Object.prototype.hasOwnProperty.call(obj, prop);
}

Теперь это работает:

has(window, 'setTimeout'); // true

даже если window.hasOwnProperty === undefined (что имеет место в IE версии 8 или ниже).

11 голосов
/ 24 августа 2011

Это действительно зависит от того, чего вы хотите достичь. Вы говорите о хост-объектах (таких как window и узлы DOM)? Если это так, самая безопасная проверка - typeof, которая работает для всех известных мне хост-объектов:

 if (typeof object.property != "undefined") { ... }

Примечания:

  • Избегайте object.hasOwnProperty() для хост-объектов, потому что хост-объекты не обязаны наследовать от Object.prototype и, следовательно, могут не иметь метода hasOwnProperty() (и, действительно, в IE <9 они обычно не имеют). </li>
  • Простое булево принуждение (например, if (object.property) { ... }) является плохим тестом существования свойства, так как оно даст ложные отрицательные значения для ложных значений. Например, для пустой текстовой области if (textarea.selectionStart) { ... } не будет выполнять блок, даже если свойство существует. Кроме того, некоторые свойства объекта хоста выдают ошибку в более старых версиях IE при попытке привести к логическому (например, var xhr = new ActiveXObject("Microsoft.XMLHTTP"); if (xhr.responseXML) { ... }).
  • Оператор in является лучшей проверкой существования свойства, но еще раз нет никаких гарантий относительно поддержки его в хост-объектах.
  • Я рекомендую не учитывать производительность для такого рода задач. Выберите наиболее безопасный вариант для вашего проекта и оптимизируйте только позже. Почти наверняка найдутся гораздо лучшие кандидаты для оптимизации, чем проверки существования свойств.

Для получения дополнительной информации по этому вопросу, я рекомендую эту прекрасную статью Питера Мишо .

2 голосов
/ 24 августа 2011

Определенно if ('property' in object) - верный путь. Это фактически проверяет, находится ли свойство в объекте (или в его цепочке прототипов, подробнее об этом ниже).

if (object.property), с другой стороны, преобразует «свойство» в истинное / ложное значение. Если свойство не установлено, оно вернет «неопределенное», которое будет приведено к значению false и будет работать. Но это также не удастся для ряда других установленных значений свойств. Общеизвестно, что javascript непоследователен в том, что он считает правдивым и ложным.

Наконец, как я уже сказал выше, 'property' in 'object' вернет true, если оно находится где-нибудь в цепочке прототипов. Если вы хотите проверить это на самом объекте, а не где-то выше в цепочке, вы используете метод hasOwnProperty следующим образом:

if (object.hasOwnProperty('property')) ...
0 голосов
/ 22 марта 2012

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

// No enclosing functions here
if (!('hasOwnProperty' in this))
    function hasOwnProperty(obj, prop) {
        var method = Object.prototype.hasOwnProperty;
        if (prop === undefined)
            return method.call(this, obj);
        return method.call(obj, prop);
    }

//Example of use
var global = global || this; //environment-agnostic way to get the global object
var x = 'blah';
WScript.Echo(global.hasOwnProperty('x') ? 'true' : 'false'); //true

//Use as non-object method
var y = { z: false };
WScript.Echo(hasOwnProperty(y, 'z') ? 'true' : 'false'); //true
WScript.Echo(hasOwnProperty(y, 'w') ? 'true' : 'false'); //false

// true ಠ_ಠ
WScript.Echo(hasOwnProperty(global, 'hasOwnProperty') ? 'true' : 'false');
0 голосов
/ 24 августа 2011

Первый из них потерпит неудачу, если «property» имеет значение false, равное 0. Чтобы убедиться, что свойство действительно существует, вам нужно проверить это object.property !== undefined или использовать ключевое слово.

[Edit]

Существует также функция hasOwnProperty, но я никогда не использовал ее, поэтому не могу много говорить об этом.Хотя я думаю, что он не вернет true, если свойство установлено в прототипе, что иногда требуется, а иногда нет.

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