JavaScript: Определен ли член?
Мне кажется, что существует четыре разных способа определить, имеет ли данный объект (например, foo
) заданное свойство (например, bar
):
-
if (foo.hasOwnProperty(bar)) {
-
if ('bar' in foo) {
-
if (typeof foo.bar !== 'undefined') {
-
if (foo.bar === undefined) {
Чтобы определить, есть ли в объекте foo
свойство с именем "bar
", все три эти выражения эквивалентны? Есть ли какая-либо субъектная семантика, которую я не знаю, что делает любое из этих трех утверждений разными?
Ответы
Ответ 1
Нет, они совершенно разные. Пример:
foo = {bar: undefined};
Object.prototype.baz = undefined;
Object.prototype.bing = "hello";
Тогда:
(typeof foo.bar != "undefined") === false
('bar' in foo) === true
(foo.hasOwnProperty('bar')) === true
(typeof foo.baz != "undefined") === false
('baz' in foo) === true
(foo.hasOwnProperty('baz')) === false
(typeof foo.bing != "undefined") === true
('bing' in foo) === true
(foo.hasOwnProperty('bing')) === false
Логика-накрест:
-
foo.hasOwnProperty('bar')
подразумевает 'bar' in foo
-
typeof foo.bar != "undefined"
означает 'bar' in foo
- Но это единственные выводы, которые вы можете сделать; никакие другие последствия не являются общепринятыми, как показывают вышеприведенные контрпримеры.
Ответ 2
Все они разные:
-
foo.hasOwnProperty('bar')
сообщает вам, имеет ли свойство foo
и не выполняет поиск по цепочке прототипов.
-
'bar' in foo
проверяет цепочку прототипов и возвращает true, когда находит свойство bar
в любом объекте вдоль цепочки.
-
typeof foo.bar != 'undefined'
возвращает true, если foo
или любой объект по цепочке прототипов имеет свойство bar
, а значение не равно undefined
.
Вот пример, демонстрирующий эти различия:
var foo1 = { 'bar1': 10, 'bar2': undefined };
function ctor() {}
ctor.prototype = foo1;
var foo2 = new ctor();
foo2.bar3 = 20;
console.log(foo2.hasOwnProperty('bar1')); // false
console.log(foo2.hasOwnProperty('bar2')); // false
console.log(foo2.hasOwnProperty('bar3')); // true
console.log(foo2.hasOwnProperty('bar4')); // false
console.log('bar1' in foo2); // true
console.log('bar2' in foo2); // true
console.log('bar3' in foo2); // true
console.log('bar4' in foo2); // false
console.log(typeof foo2.bar1 != 'undefined'); // true
console.log(typeof foo2.bar2 != 'undefined'); // false
console.log(typeof foo2.bar3 != 'undefined'); // true
console.log(typeof foo2.bar4 != 'undefined'); // false
Ответ 3
одно отличие состоит в том, что метод 1 будет проверять только объект foo для панели свойств, в то время как последние два метода также будут проверять прототип для унаследованного свойства.
Ответ 4
'bar' in foo
будет выглядеть в любом месте цепи прототипов. Тестирование, чтобы увидеть, если foo.bar
! == undefined
также вернет true, если bar
находится где угодно в цепочке прототипов foo
, но помните, если bar определен на foo, а установлен на w90 > , это вернет false.
hasOwnProperty более разборчиво - он вернет true, а bar
определяется как прямое свойство foo
.
За MDN
Каждый объект, сгенерированный из Object, наследует метод hasOwnProperty. Этот метод может быть использован для определения того, имеет ли объект указанное свойство как прямое свойство этого объекта; в отличие от оператора, этот метод не проверяет прототип объекта цепь.
Ответ 5
Есть действительно некоторые тонкие различия между различными методами/ключевыми словами.
-
foo.hasOwnProperty('bar')
возвращает значение true, только если свойство "bar" определено в самом объекте foo. Другие свойства, такие как 'toString', возвращают false, поскольку они определены цепочкой прототипов.
-
Оператор ключевого слова in
возвращает true, если указанное свойство находится в указанном объекте. Оба 'bar' in foo
и 'toString' in foo
вернут true.
-
Поскольку вы проверяете состояние свойства, результат будет истинным, если bar не определен в foo и когда bar определен, но значение установлено на undefined
.
Ответ 6
Чтобы добавить к словам других, если вы просто хотите знать, существует ли свойство и имеет значение без ложности (не undefined
, null
, false
, 0
, ""
, NaN
и т.д.), вы можете просто сделать это:
if (foo.bar) {
// code here
}
Пока значения для вас не интересны для ваших конкретных обстоятельств, этот ярлык подскажет вам, была ли переменная настроена на что-то полезное для вас или нет.
Если вы хотите узнать, существует ли свойство на объекте каким-либо образом, я считаю это наиболее полезным, кратким и читаемым:
if ('bar' in foo) {
// code here
}
Можно также использовать что-то подобное в аргументах функции (опять же, пока значение ложности не является чем-то, о чем вы заботитесь):
function foo(bar) {
if (bar) {
// bar was passed and has some non-falsey value
}
}