How to Get the Keys of an Object in JavaScript

get object keys js
Get Object Keys in javascript

The article looks at the different ways to get the keys of an object in JavaScript. You will become intimately familiar with the necessary toolkit for extracting keys. It allows us to use varied techniques like Object.getOwnPropertyNames() and Object.keys() that make the solution of the task possible. In the sections below, we will analyze their drawbacks and advantages, as well as their similarities and differences.

Techniques for extracting object keys in JavaScript

Use one of the following methods to get the keys of an object:

  1. Object.keys() returns an array of enumerable keys.
  2. Object.getOwnPropertyNames() returns enumerable and non-enumerable keys.
  3. Reflect.ownKeys() returns enumerable and non-enumerable keys.
  4. Object.getOwnPropertySymbols() returns enumerable and non-enumerable symbol keys.

Get the keys of an object using Object.keys()

The method returns an array of strings whose values are the enumerable keys of the object passed as a parameter. It extracts only the keys owned by the object directly.

const person = {
  name: 'Martin',
  age: 27,

  printName: function() {
    console.log('My name is: ' + this.name);
  }
};

// printing all the keys from the person object
console.log(Object.keys(person));

Output:

['name', 'age', 'printName']

We defined the object ‘person’ and printed its keys as an array on the console.

Object.keys() and inherited keys

The method doesn’t return inherited keys. Look at the example below:

const person = {
  name: 'Martin',
  age: 27,
  printName: function() {
    console.log('My name is: ' + this.name);
  }
};

// creates a new object with the prototype of the existing one
const teacher = Object.create(person);
// adding new keys and only they will be extracted 
teacher.subject = 'Psychology'
teacher.salary = 2000;

// gets the object's own keys
console.log(Object.keys(teacher)); // --> ['subject', 'salary']
console.log(`Teacher's name is: ${teacher.name}`); // Teacher's name is: Martin
console.log(`Person's name is: ${person.name}`); 

// we can access the printName method
console.log(teacher.printName());
console.log(person.printName());

We defined the person object using object literal notation and added keys: name, age, and a method called printName.

We created an additional object teacher using Object.create(). It inherited all the keys of the person object. We also added the keys: subject and salary, so they became the teacher’s own.

We got all teacher’s own keys with Object.keys(teacher). As you can see, it didn’t print the inherited keys from the person object.

Look at the output:

['subject', 'salary']
Teacher's name is: Martin
Person's name is: Martin
My name is: Martin
My name is: Martin

It displays only the subject and salary because they reside directly on the teacher object. We can still access the name key and the printName method with ‘teacher.printName() and teacher.name,’ but they aren’t included in the returned array of keys.

Object.keys() and non-enumerable keys

If a key is defined as a non-enumerable, the Object.keys() method won’t include it in the returned array. Let’s try to create an example with Object.defineProperty(). It will give us a clearer idea.

const person = {};

// by default keys defined by the defineProperty method will be non-enumerable
Object.defineProperty(person, 'age', {
  value: 42
});

// setting the enumerable configuration to true, so the name key will be enumerable
Object.defineProperty(person, 'name', {
  value: 'Martin',
  enumerable: true
});

// printing only enumerable keys
console.log(Object.keys(person)); //['name']

Output:

['name']

The previous code snippet creates an empty ‘person’ object, adds two properties to it using the Object.defineProperty() method, and then logs the enumerable property names of ‘person’ to the console using Object.keys(). When a property is defined by Object.defineProperty() automatically becomes non-enumerable.

Get the keys of an object in JavaScript using Object.getOwnPropertyNames()

The method returns an array of enumerable and non-enumerable keys of the object passed as a parameter. The property names are string values. The method returns only keys that are directly upon the object.

const person = {
  salary: 2000,
  surname: 'Smith'
};

// define new key age
// explicitly setting the enumerable configuration
Object.defineProperty(person, 'age', {
  value: 42,
  enumerable: false
});

// define new key name
// explicitly setting the enumerable configuration
Object.defineProperty(person, 'name', {
  value: 'Martin',
  enumerable: false
});

// getting all object keys -   enumerable and non-enumerable
console.log(Object.getOwnPropertyNames(person)); // ['salary', 'surname', 'age', 'name']

Output:

['salary', 'surname', 'age', 'name']

We defined an object person with two keys: salary and surname using object literal syntax. We added two more properties age and name to it using the Object.defineProperty() method, then we added explicitly false to the enumerable configuration (it is false by default). Afterward, we printed all keys of the person object to the console using the Object.getOwnPropertyNames() method.

Object.getOwnPropertyNames() and inherited keys

Object.getOwnPropertyNames() doesn’t include inherited keys in the returned array.

const person = {
  name: 'David',
  age: 149,
};
const teacher = Object.create(person);
teacher.subject = 'Math';
teacher.salary = 2000;

// returns only the keys that are directly upon the teacher object
console.log(Object.getOwnPropertyNames(teacher)); //['subject', 'salary']

Output:

['subject', 'salary']

The object teacher inherits the name and age keys from the person object because we used the Object.create() method. It also has its own property names: subject and salary, which will be included in the array returned from Object.getOwnPropertyNames(teacher). The inherited ones are excluded from the result.

Get the keys of an object using Reflect.ownKeys()

The method returns an array of enumerable and non-enumerable keys of the passed object. They can be symbols and strings.

const person = {
  name: 'David',
  age: 20,
};

// creating a key to be Symbol
person[Symbol('surname')] = 'Smith';

// define a non-enumerable key 'height'
Object.defineProperty(person, 'height', {
  value: '187',
  enumerable: false
});

// it returns an array of all keys - enumerable,
// non-enumerable, symbols and string
console.log(Reflect.ownKeys(person)); // ['name', 'age', 'height', Symbol(surname)]

Output:

['name', 'age', 'height', Symbol(surname)]

We created the surname key to be of type Symbol, then defined a non-enumerable property named height using Object.defineProperty(). All keys are included in the returned array regardless of the value of the enumerable configuration or the type of key.

Reflect.ownKeys() and inherited keys

As the method name suggests (ownKeys()), it returns only keys directly upon the given object.

// we created person with keys: name and age
const person = {
  name: 'David',
  age: 20,
};

// we added a symbol key to person
person[Symbol('surname')] = 'Smith';

// we created new object with the prototype of the person object
// this means, that the person inherits the name, age and surname keys
const teacher = Object.create(person);

teacher.subject = 'Math';
// we added a symbol key to teacher
teacher[Symbol('salary')] = 2000;

console.log(Reflect.ownKeys(teacher)); //['subject', Symbol(salary)]

Output:

['subject', Symbol(salary)]

The teacher object holds the keys: subject and salary directly upon itself. It inherited name, age, and surname from the person object, but they don’t reside upon teacher.

Get the keys of an object using Object.getOwnPropertySymbols()

The method returns only symbol keys that reside directly upon the passed object, whether the properties are enumerable or non-enumerable.

const person = {
  name: 'David',
  age: 20,
};

// creating a key to be Symbol
person[Symbol('surname')] = 'Smith';

// define a non-enumerable symbol key 'height'
Object.defineProperty(person, Symbol('height'), {
  value: '187',
  enumerable: false
});

// it returns an array of the symbol keys - enumerable,
// non-enumerable, only symbols 
console.log(Object.getOwnPropertySymbols(person)); // [Symbol(surname), Symbol(height)]

Output:

 [Symbol(surname), Symbol(height)]

Object.getOwnPropertySymbols() and inherited keys

This method also behaves as all others above in a matter of inherited properties. The main difference between Object.getOwnPropertySymbols() and Reflect.ownKeys() is that Object.getOwnPropertySymbols() returns only keys defined as Symbols.

const person = {
  name: 'David',
  age: 20,
};


person[Symbol('surname')] = 'Smith';

const teacher = Object.create(person);
teacher.subject = 'Math';

teacher[Symbol('salary')] = 2000;

console.log(Object.getOwnPropertySymbols(teacher)); // [Symbol(salary)]

Output:

[Symbol(salary)]

Pitfalls with inherited keys

NOTE: You may think that when an object inherits another object using a class with extends keyword or using a constructor function, the inherited keys won’t be included in the array returned from one of the previously mentioned methods (Object.keys, Object.getOwnPropertySymbols(), etc.) but that’s NOT the case.

When you use a class with the extends keyword, all the properties are copied in the subclass. That means the subclass possesses them directly.

Another similar example – Imagine an object teacher created by Object.create(). We have a property name upon the object person used as a prototype. Hence, the teacher can access teacher.name. If we add a new value to teacher.name = ‘…’, the name key will be found upon teacher, but the person’s name property will also stay unaltered upon person.

const person = {
  name: 'David',
  age: 149,
};

const teacher = Object.create(person);
teacher.subject = 'Math';
teacher.salary = 2000;

// it returns the key that resides upon person
console.log(teacher.name); // --> David

// we added a new name property to teacher which is exactly the same as person
teacher.name = 'Martin';

// now the teacher has it's own property name
console.log(teacher.name); // --> Martin

// look at the person's name 
// the person's name property stays the same
console.log(`Person's name: ${ person.name } `); // --> David

// returns only the keys that are directly upon the teacher object
// now teacher has it's own name property
console.log(Object.getOwnPropertyNames(teacher)); // ['subject', 'salary', 'name']

Output:

David
Martin
Person's name: David 
['subject', 'salary', 'name']

Similar Posts