1

"Iterables" in JavaScript are objects with a Symbol.iterator property. For example:

let x = { 
  [Symbol.iterator]: function * () { 
    yield * [ 1, 2, 3]; 
  } 
};

[ ...x ] // Array [ 1, 2, 3 ]

So Symbol.iterator is just a convention.

But why was this concept, Symbol, invented when a string could have done a similar job?

let x = { 
  iterator: function * () { 
    yield * [ 1, 2, 3 ]; 
  } 
};

// Invalid, but would be equivalent to [ ...x['iterator']() ]
[ ...x ] 
sdgfsdh
  • 33,689
  • 26
  • 132
  • 245
  • 2
    My guess is that symbols are guaranteed to be unique and not cause name collisions, also probably more efficient than strings. This is pure speculation on my part though. – Máté Safranka Apr 05 '18 at 16:07

3 Answers3

4

Symbol.iterator is a symbol so you can't copy or recreate it. This eliminates the possiblity that you could overwrite it accidently.

I encourage you to watch this video about Symbols in JavaScript.

Sebastian Speitel
  • 7,166
  • 2
  • 19
  • 38
2

Symbols are explained in some detail at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol

In particular:

Note that Symbol("foo") does not coerce the string "foo" into a symbol. It creates a new symbol each time:

Symbol('foo') === Symbol('foo'); // false

Let's say I have some data that I want to store in some widely-visible object. I can come up with a string, say "foo", and use that as the key to store my data in the object. Later on, I can use that same string (either hard-coded or stored somewhere) to get my data back out of the object.

There are two things to keep in mind if we do this: any other code can look up our data, and any other code can overwrite our data either intentionally or by accident (e.g. they just so happened to pick the same string as us).

If we use a symbol as a key instead, then there is no way for other code to look up or modify the data, unless we explicitly give them the symbol (e.g. as an argument). This way, clashes can't occur, since lots of different code can all use the same string (like "foo" in the MDN example) but they'll always end up with different symbols, so there's no conflict.

One reason we might want to do this is if we have a single "state" object which various pieces of code will modify. If we want to keep each piece of code modular then it's important that they don't end up depending on each other indirectly via the state: by using symbols we make sure that not only can a piece of code not alter someone else's part of the state, but they also can't depend on someone else's state (i.e. choosing what to do based on reading someone's state).

Warbo
  • 2,611
  • 1
  • 29
  • 23
  • 2
    "If we use a symbol as a key instead, then there is no way for other code to look up or modify the data, unless we explicitly give them the symbol" This isn't strictly true. `Object.getOwnPropertySymbols` exists, and thus using symbols does *not* guarantee against malicious changes, just accidental ones. – Stone Mason Aug 26 '19 at 00:24
0

Symbols provide a solid way of guaranteeing that no accidental property name collisions can occur. It's always possible that a string property name might inadvertently be used for a completely different purpose. Symbol instances are guaranteed to be unique; it's not possible to create two Symbol instances that compare as === to each other.

Pointy
  • 405,095
  • 59
  • 585
  • 614