How to Understand Symbol and Iterators in JavaScript
A step-by-step guide on how Symbols work as unique property keys and how the iterator protocol enables custom iteration in JavaScript.
Understand What Symbol Is
Symbol is a primitive data type introduced in ES6. Every Symbol value is guaranteed to be unique, even if two Symbols are created with identical description strings. Call Symbol with an optional description string and it returns a new unique value each time. Symbols are never automatically converted to strings and cannot be created with the new keyword. They are primarily used as unique property keys.
Use Symbols as Object Property Keys
Object property keys are typically strings. Using Symbols as keys guarantees no property name collision because no two Symbols are equal. Add a Symbol as an object property using square bracket notation. Symbol-keyed properties do not appear in for-in loops, Object.keys, Object.values, or Object.entries. They are also not included in JSON.stringify output, making them useful for metadata that should not be exposed.
Understand Well-Known Symbols
JavaScript provides a set of built-in well-known Symbols on the Symbol object that allow you to customize the behavior of objects in response to built-in JavaScript operations. Symbol.iterator defines the default iteration behavior. Symbol.toPrimitive controls type coercion. Symbol.hasInstance controls instanceof behavior. Symbol.toStringTag customizes the output of Object.prototype.toString. These hooks let you make objects behave natively with JavaScript's built-in operations.
Understand the Iterator Protocol
The iterator protocol defines a standard way to produce a sequence of values. An object is an iterator if it has a next method that returns an object with two properties: value which is the current value in the sequence, and done which is a boolean that is false while there are more values and true when the sequence is exhausted. This protocol is what for-of loops, spread, and destructuring use internally.
Understand the Iterable Protocol
An object is iterable if it has a property keyed with Symbol.iterator whose value is a function that returns an iterator. Arrays, strings, Maps, Sets, and generator objects are all built-in iterables because they implement this protocol. When you use a for-of loop, JavaScript calls the Symbol.iterator method on the object to get an iterator and then calls next repeatedly until done is true.
Create a Custom Iterable Object
To make any object iterable, add a method keyed with Symbol.iterator that returns an iterator object with a next method. Inside next, track the current state and return the appropriate value and done pair. Once you implement this, your custom object works with for-of loops, spread operator, destructuring, Array.from, and any other construct that uses the iterable protocol.
Combine Symbol.iterator with Generator Functions
A generator function automatically returns an object that satisfies both the iterator and iterable protocols. The cleanest way to implement a custom iterable is to set the Symbol.iterator method of your object to a generator function. The generator's yield statements define each value in the sequence. This approach is far simpler than manually implementing next with state tracking.
Use Symbol.toPrimitive for Custom Type Coercion
When JavaScript needs to convert an object to a primitive for operations like addition or comparison, it calls the Symbol.toPrimitive method if it exists on the object. This method receives a hint string which is either 'number', 'string', or 'default'. Based on the hint, return the appropriate primitive value. This lets you control exactly how your custom objects behave in arithmetic, string concatenation, and comparison operations.
Ready to master this completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.

