Способы проверки наличия свойства объекта

В чём принципиальная разница между разными способами проверки наличия свойства в объекте\массиве JS? Может есть разница в производительности или вопрос только в личных предпочтениях программиста?

Приведу примеры таких проверок, он далеко не полный, только те, с которыми мне приходилось сталкиваться:

if (key in obj){
   //code
}

if (obj.hasOwnProperty('key')){
   //code
}

if (typeof obj['key'] !== "undefined") {
   //code
}

и даже такой:

if(Object.keys(obj).includes('key')){
   //code
}

Ответы (1 шт):

Автор решения: 1ocke

Начну с различия оператора in и метода hasOwnProperty.

Оператор in ищет наличие ключей не только в самом объекте, но и в его прототипах. А метод hasOwnProperty только в конкретном объекте.

const obj = {
  key: 'value',
};

console.log('key' in obj); // true
console.log(obj.hasOwnProperty('key')); // true

console.log('toString' in obj); // true
console.log(obj.hasOwnProperty('toString')); // false

Также стоит упомянуть тот факт, что если мы изменим значение ключа в исходном объекте на undefined, то оператор in все равно вернет true, что логично, так как свойство по-прежнему есть в объекте.

const obj = {
  key: undefined,
};

console.log('key' in obj); // true

C typeof есть один нюанс. Он нормально отработает, если искомого ключа нет в объекте. А если значение есть, но оно равно undefined, то мы получим не тот результат, который ожидали.

const obj = {
  key: undefined,
};

console.log(typeof obj['key2'] !== "undefined"); // false
console.log(typeof obj['key'] !== "undefined"); // false, ключа нет

Ну, а способ с Object.keys просто пройдется по массиву ключей и вернет true, если найдет искомый ключ. И опять же метод keys вернет ключи конкретного объекта, не затрагивая его прототипы.

class SomeObj {
  constructor(value) {
    this.key1 = value;
  }
}

SomeObj.prototype.key2 = 'other value';

const obj = new SomeObj('value');

console.log(Object.keys(obj)); // ['key1']

for (key in obj) {
  console.log(key); // key1, key2
}

Короче говоря, лучше использовать способ, который не сравнивает значения и не создает массив для поиска в нем ключей. По крайней мере это семантически неправильно. А из оператора in и метода hasOwnProperty уже надо выбирать тот, который подходит для решения конкретной задачи.

Еще замечу, что при использовании метода hasOwnProperty линтер (eslint) может ругаться на его использование. Происходит это потому, что есть возможность перезаписи метода.

→ Ссылка