Master JavaScript Object Traversal: keys(), values(), entries() & Custom Iterators

This article explains the differences between Object.keys/values/entries and their array counterparts, shows how to use them for object property iteration, demonstrates creating custom iterator methods for plain objects, and compares iterator results with array returns, providing code examples and visual diagrams.

WeDoctor Frontend Technology
WeDoctor Frontend Technology
WeDoctor Frontend Technology
Master JavaScript Object Traversal: keys(), values(), entries() & Custom Iterators

Background

The story begins with a confusion when traversing arrays and object properties: whether to use obj.keys(), obj.values(), obj.entries() or the static methods Object.keys(obj), Object.values(obj), Object.entries(obj).

keys(), values(), entries() traversal methods

Native object structures do not support obj.keys(), obj.values(), or obj.entries(); only arrays, Map, Set, etc., have those methods. However, Object.keys(obj), Object.values(obj), and Object.entries(obj) can retrieve an object's own enumerable property names, values, or [key, value] pairs as arrays.

There are two versions of these methods:

ES5‑ES2017 introduced Object.keys, Object.values, and Object.entries, returning arrays of an object's own enumerable keys, values, or entries, which can be iterated with for...of.

ES6 added entries(), keys(), and values() for array‑like structures, returning an iterator object.

Key differences:

The call syntax differs: static methods vs. prototype methods.

The static methods return a true array, while the prototype methods return an iterator.

Q1: Object.keys, Object.values and Object.entries

These static methods operate on the Object prototype's constructor. The following diagram shows their placement in the prototype chain for a plain object:

For an array, the same three methods can be found both on the array prototype and higher‑level prototype constructors:

Thus, Object.keys(arr) calls the method defined on the top‑level prototype, while arr.keys() invokes the array’s own prototype method.

Q2: Enabling obj.keys(), obj.values() and obj.entries() on a plain object

By adding a custom iterator to an object, we can mimic array‑like traversal. The following code creates an object with its own keys method that returns an iterator:

let objE = {<br/>  data: ['hello', 'world'],<br/>  keys: function() {<br/>    const self = this;<br/>    return {<br/>      [Symbol.iterator]() {<br/>        let index = 0;<br/>        return {<br/>          next() {<br/>            if (index < self.data.length) {<br/>              return { value: self.data[index++], done: false };<br/>            }<br/>            return { value: undefined, done: true };<br/>          }<br/>        };<br/>      }<br/>    };<br/>  }<br/>};

The object now supports Object.values(data) and its own iterator. The diagram below illustrates the added Symbol.iterator:

Q3: Return differences – iterator vs. array

The static methods return arrays containing only the object's own enumerable properties. The iterator methods return an iterator object that can be consumed by for...of loops.

Using for...in can achieve similar results, but for...of works directly with iterators.

Iterator Overview

Four main collection‑like structures—Array, Object, Map, and Set—can be traversed via iterators. Native structures that implement the Iterator interface include Array, Map, Set, String, TypedArray, arguments, and NodeList.

Iterators provide a unified access mechanism for all iterable data structures, enabling for...of loops.

1. Traversing array‑like structures

When a for...of loop runs, it looks for the Symbol.iterator property. Any object with this property is considered iterable.

2. Getting an object's enumerable properties

Object.keys

, Object.values, and Object.entries return only the object's own enumerable properties. Plain objects are not iterable because they lack Symbol.iterator, so for...of throws a TypeError.

3. Using for...of

Introduced in ES6, for...of offers concise syntax, supports break, continue, and return, and works across all iterable structures.

To make a plain object iterable, we can implement Symbol.iterator as shown:

// plain object<br/>const obj = {<br/>  foo: 'value1',<br/>  bar: 'value2',<br/>  [Symbol.iterator]() {<br/>    const keys = Object.keys(obj);<br/>    let index = 0;<br/>    return {<br/>      next: () => {<br/>        if (index < keys.length) {<br/>          return { value: this[keys[index++]], done: false };<br/>        } else {<br/>          return { value: undefined, done: true };<br/>        }<br/>      }<br/>    };<br/>  }<br/>};<br/>for (const value of obj) {<br/>  console.log(value); // value1 value2<br/>}

This enables for...of to iterate over plain objects just like arrays.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

IteratorKEYSvaluesentriesObject Traversal
WeDoctor Frontend Technology
Written by

WeDoctor Frontend Technology

Official WeDoctor Group frontend public account, sharing original tech articles, events, job postings, and occasional daily updates from our tech team.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.