The main use case for ES6 symbols is that you can use them as property keys that can’t clash with other property keys.
In case you think that name clashes don’t matter, here are three examples of where name clashes caused problems in the evolution of the JavaScript standard library:
When the new method Array.prototype.values()
was created, it broke existing code where with
was used with an Array and shadowed a variable values
in an outer scope (bug report 1, bug report 2). Therefore, a mechanism was introduced to hide properties from with
(Symbol.unscopables
).
String.prototype.contains
clashed with a method added by MooTools and had to be renamed to String.prototype.includes
(bug report).
The upcoming Array.prototype.contains
also clashed with a method added by MooTools and had to be renamed to Array.prototype.includes
(bug report).
In contrast, adding iterability to an object via the property key Symbol.iterator
can’t cause problems, because that key doesn’t clash with anything.
These examples demonstrate what it means to be a web language: backward compatibility is crucial, which is why compromises are occasionally necessary when evolving the language. As a side benefit, evolving old JavaScript code bases is simpler, too, because new ECMAScript versions never (well, hardly ever) break them.