← Назад к вопросам

В чем разница между Object.keys и Object.getOwnPropertyNames?

2.0 Middle🔥 133 комментариев
#JavaScript Core

Комментарии (3)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между Object.keys и Object.getOwnPropertyNames

Object.keys и Object.getOwnPropertyNames — это два похожих метода для получения свойств объекта, но они работают по-разному. Основное отличие в том, какие свойства они возвращают.

Object.keys

Object.keys() возвращает массив только перечисляемых собственных свойств объекта. Это свойства, которые видны в цикле for...in и помечены как enumerable: true.

const user = {
  name: "Иван",
  age: 25,
  email: "ivan@mail.com"
};

const keys = Object.keys(user);
console.log(keys); // ["name", "age", "email"]

Object.getOwnPropertyNames

Object.getOwnPropertyNames() возвращает массив всех собственных свойств, включая неперечисляемые. Но не включает символы.

const user = {};

// Создаем перечисляемое свойство (по умолчанию)
Object.defineProperty(user, "name", {
  value: "Иван",
  enumerable: true
});

// Создаем неперечисляемое свойство
Object.defineProperty(user, "password", {
  value: "secret123",
  enumerable: false
});

const keys = Object.keys(user);
console.log(keys); // ["name"] - только перечисляемые

const allKeys = Object.getOwnPropertyNames(user);
console.log(allKeys); // ["name", "password"] - все свойства

Практический пример 1: Обычный объект

const person = {
  firstName: "Иван",
  lastName: "Петров",
  age: 25
};

// Object.keys
console.log(Object.keys(person));
// ["firstName", "lastName", "age"]

// Object.getOwnPropertyNames
console.log(Object.getOwnPropertyNames(person));
// ["firstName", "lastName", "age"]

// В этом случае результаты одинаковые, потому что все свойства перечисляемые

Практический пример 2: Объект с неперечисляемыми свойствами

const obj = {
  visible: "видно"
};

// Добавляем неперечисляемое свойство
Object.defineProperty(obj, "hidden", {
  value: "не видно",
  enumerable: false // неперечисляемо
});

console.log(Object.keys(obj));
// ["visible"] - видны только перечисляемые

console.log(Object.getOwnPropertyNames(obj));
// ["visible", "hidden"] - видны все

Практический пример 3: Класс с методами

class User {
  constructor(name) {
    this.name = name;
  }
  
  greet() {
    console.log("Привет, я " + this.name);
  }
}

const user = new User("Иван");

console.log(Object.keys(user));
// ["name"] - только собственные свойства экземпляра

console.log(Object.getOwnPropertyNames(user));
// ["name"] - то же, что keys (name перечисляемо)

console.log(Object.getOwnPropertyNames(User.prototype));
// ["constructor", "greet"] - методы класса (не перечисляемы по умолчанию)

Сравнительная таблица

МетодПеречисляемыеНеперечисляемыеСимволыУнаследованные
Object.keysДАНЕТНЕТНЕТ
Object.getOwnPropertyNamesДАДАНЕТНЕТ
for...inДАНЕТНЕТДА
Object.getOwnPropertySymbols--ДАНЕТ

Практический пример 4: Приватные данные

const obj = {
  publicData: "видимо всем"
};

// Приватные данные (неперечисляемые)
Object.defineProperty(obj, "_privateData", {
  value: "только для использования внутри",
  enumerable: false
});

console.log(Object.keys(obj));
// ["publicData"]

console.log(Object.getOwnPropertyNames(obj));
// ["publicData", "_privateData"]

// Доступ все равно возможен
console.log(obj._privateData); // "только для использования внутри"

Практический пример 5: Копирование объекта

const original = {};

Object.defineProperty(original, "visible", {
  value: "видно",
  enumerable: true
});

Object.defineProperty(original, "hidden", {
  value: "не видно",
  enumerable: false
});

// Копирование только перечисляемых (неправильно!)
const copy1 = {};
Object.keys(original).forEach(key => {
  copy1[key] = original[key];
});
console.log(copy1); // { visible: "видно" } - потеряется hidden

// Копирование всех свойств (правильно!)
const copy2 = {};
Object.getOwnPropertyNames(original).forEach(key => {
  copy2[key] = original[key];
});
console.log(copy2); // { visible: "видно", hidden: "не видно" }

// Или использовать Object.assign (копирует перечисляемые)
const copy3 = Object.assign({}, original);
console.log(copy3); // { visible: "видно" }

Практический пример 6: Итерирование по свойствам

const user = {
  name: "Иван",
  email: "ivan@mail.com"
};

// Скрытое свойство
Object.defineProperty(user, "_id", {
  value: 123,
  enumerable: false
});

// Способ 1: Object.keys (только видимые)
Object.keys(user).forEach(key => {
  console.log(`${key}: ${user[key]}`);
});
// name: Иван
// email: ivan@mail.com

// Способ 2: Object.getOwnPropertyNames (все)
Object.getOwnPropertyNames(user).forEach(key => {
  console.log(`${key}: ${user[key]}`);
});
// name: Иван
// email: ivan@mail.com
// _id: 123

// Способ 3: for...in (видимые и унаследованные)
for (let key in user) {
  console.log(`${key}: ${user[key]}`);
}
// name: Иван
// email: ivan@mail.com

Практический пример 7: Символы

const obj = {
  name: "Иван"
};

const sym = Symbol("id");
obj[sym] = 123;

console.log(Object.keys(obj));
// ["name"] - символы не включаются

console.log(Object.getOwnPropertyNames(obj));
// ["name"] - символы не включаются

console.log(Object.getOwnPropertySymbols(obj));
// [Symbol(id)] - отдельный метод для символов

Когда использовать какой метод

Object.keys():

  • Когда нужны только перечисляемые свойства
  • Для сериализации объекта в JSON
  • Для обычного итерирования по видимым свойствам
  • Это более "безопасный" вариант
const user = { name: "Иван", age: 25 };
const json = JSON.stringify(Object.keys(user)); // "[\"name\",\"age\"]"

Object.getOwnPropertyNames():

  • Когда нужны все свойства, включая скрытые
  • При работе с приватными данными
  • При полном копировании объекта
  • При анализе структуры объекта
const obj = { visible: "да" };
Object.defineProperty(obj, "hidden", { value: "скрыто", enumerable: false });

// Получить ВСЕ свойства
const allKeys = Object.getOwnPropertyNames(obj); // ["visible", "hidden"]

Совет: Получить все (включая символы)

function getAllProperties(obj) {
  const keys = Object.getOwnPropertyNames(obj);
  const symbols = Object.getOwnPropertySymbols(obj);
  return [...keys, ...symbols];
}

const obj = { name: "Иван" };
const sym = Symbol("id");
obj[sym] = 123;

console.log(getAllProperties(obj));
// ["name", Symbol(id)]

Ключевые выводы

  1. Object.keys() возвращает только перечисляемые свойства
  2. Object.getOwnPropertyNames() возвращает все свойства (кроме символов)
  3. Оба метода возвращают только собственные свойства объекта (не унаследованные)
  4. Для символов используйте Object.getOwnPropertySymbols()
  5. for...in возвращает перечисляемые свойства, включая унаследованные
В чем разница между Object.keys и Object.getOwnPropertyNames? | PrepBro