Object.hasOwn в JavaScript: своё свойство, наследование и undefined

Object.hasOwn в JavaScript: своё свойство, наследование и undefined
Содержание статьи

Если нужно узнать, есть ли поле непосредственно у объекта, используйте Object.hasOwn. Оператор in учитывает также цепочку прототипов, а сравнение значения с undefined решает другую задачу. На Mentoring.digital разберём разницу на маленьком объекте настроек.

Сравните три разные проверки

const defaults = { role: "guest" };
const settings = Object.create(defaults);
settings.theme = undefined;

console.log("role" in settings); // true
console.log(Object.hasOwn(settings, "role")); // false
console.log(Object.hasOwn(settings, "theme")); // true
console.log(settings.theme !== undefined); // false

Role находится в прототипе. Поэтому in его видит, но hasOwn возвращает false. Theme принадлежит settings, даже если его значение равно undefined. Наличие свойства и наличие полезного значения здесь нужно проверять раздельно.

Это различие важно, когда отсутствие поля означает «оставить прежнюю настройку», а явно переданное значение означает отдельное действие. Правила обработки null и undefined всё равно задаёт ваше приложение, метод проверки их не придумывает.

Почему статический метод удобнее вызова из объекта

У объекта может быть собственное поле hasOwnProperty, которое перекрывает одноимённый метод. Кроме того, объект можно создать вообще без прототипа. Object.hasOwn вызывается у Object и не зависит от наличия такого метода у проверяемого значения.

const dictionary = Object.create(null);
dictionary.hasOwnProperty = "ordinary data";
dictionary.count = 0;

console.log(Object.hasOwn(dictionary, "count")); // true
console.log(Object.hasOwn(dictionary, "missing")); // false

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

Добавьте проверку данных на границе

Если вход может быть null или примитивом, сначала определите, что в задаче считается допустимым объектом. Ниже в качестве настроек принимается непустой объект, который не является массивом. После этого отдельно проверяется тип поля.

function hasNumericCount(value) {
  return value !== null
    && typeof value === "object"
    && !Array.isArray(value)
    && Object.hasOwn(value, "count")
    && typeof value.count === "number"
    && Number.isFinite(value.count);
}

Это проверка только одного поля и оговорённой формы входа, а не универсальная валидация JSON. Решите отдельно, допустимы ли отрицательные и дробные значения. Проверка собственного свойства также не удаляет лишние поля из объекта.

Задание: сравните результаты для {}, {count: 0}, {count: undefined}, null и объекта с count в прототипе. Затем добавьте требование неотрицательного целого числа. Основы объектов можно закрепить на курсе JavaScript, а модель входных данных разобрать с наставником по JavaScript.

Похожие статьи по данной теме