10

What is the use of Symbol in javascript (ECMASCRIPT6)?

Why does the example below return false?

const symbol1 = Symbol();

console.log(Symbol('foo') === Symbol('foo'));
// expected output: false
nicael
  • 18,550
  • 13
  • 57
  • 90
Mohamed Ben HEnda
  • 2,686
  • 1
  • 30
  • 44
  • 2
    The [MDN docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol) are pretty clear: "Every symbol value returned from Symbol() is unique." – rmlan Apr 02 '18 at 17:43
  • @Bergi lol, nice find, I have now no idea what I was answering for here and collecting the data for my answer to this question, without noticing that it's already answered. That question should probably get a more-findable title (*edited the title of that question*) – nicael Apr 02 '18 at 18:56
  • @nicael You can still delete your (good!) answer here and repost it there for a larger audience – Bergi Apr 02 '18 at 19:02
  • @Bergi Done that, thanks for a suggestion. – nicael Apr 02 '18 at 19:29

3 Answers3

14

Symbol is used to create a totally unique, one-of-a-kind identifier. It's use is precisely for the example you list.

Even if you call Symbol with the same string, the instances will be different. This allows different libraries (which may be used at the same time) to define keys which may be used at the same time.

For example, imagine two libraries using a common name to define something on window or global (or for illustration, the fake global door):

const door = {};
// from library 1
door.cake = () => console.log('chocolate');
// from library 2
door.cake = () => console.log('vanilla');

// your code
door.cake();

In this example, the first libraries code is lost because it was unintentionally given the same name as the first.

Now, if they both use Symbol, then even if they are named the same, you can still access both (assuming they export Symbol somehow):

const door = {};
// library 1
const cake1 = Symbol('cake');
door[cake1] = () => console.log('chocolate');
// library 2
const cake2 = Symbol('cake');
door[cake2] = () => console.log('vanilla');
// your code
door[cake1]();
door[cake2]();

Both are still accessible.

That is a bit of an oversimplification, but it illustrated the point.

In a more practical usage, these are used for things such as importing modules. The modules may end up with the same name, but that's okay because they'll have unique symbols associated with them, which makes them uniquely accessible as long as your have the Symbol objects.

As for when to use them yourself... it's probably going to be pretty rare. You'll mainly want to use them any time you have a way to provide the Symbol but need other things to remain unique. I've only used these directly in a few narrow circumstances where the created element may end up the same.

For example, if you were making an object using names as the key, you might have duplicate names. Without symbols, the objects would override one other. With symbols, they'll all remain.

const people = {};
people[Symbol('bob')] = { name: 'Bob Smith' };
people[Symbol('bob')] = { name: 'Bob Jones' };
samanime
  • 25,408
  • 15
  • 90
  • 139
  • I've tried to ask a question at https://stackoverflow.com/questions/59768559/whats-the-purpose-of-symbol-in-terms-of-unique-object-identifiers and been told it's a duplicate of this. The only thing that makes your code run is because `cake1` and `cake2` have different names, but these have been assigned by the developer. How does `Symbol` help in this situation? If you renamed `cake1` and `cake2` as `cake` you'd get an error because they are **not unique**. If `Symbol` is supposed to alleviate the unique problem, it doesn't seem to be helping here. – Andy Jan 16 '20 at 12:01
  • 1
    You are getting values to use as keys confused with variable names. You can't redeclare the same variable name in the same scope (nor should you) if you are using let or const. That has nothing to do with Symbol though. Symbol is to ensure that every time you call `Symbol` you get a wholly unique identifier no mater what. The "same" thing I set was `Symbol('cake')` for both to show even though I created two symbols with the same name (or "description" as the parameter is probably called) it generates two unique Symbols. When you use those as keys in objects, they refer to two different things. – samanime Jan 16 '20 at 18:03
7

From the documentation:

Every symbol value returned from Symbol() is unique.

That means === comparisons will fail because they're not identical.

If you want a unique identifier of some sort that can be given a descriptive, if otherwise irrelevant name, then Symbol might be useful.

tadman
  • 208,517
  • 23
  • 234
  • 262
2

The Idea of the symbol is to introduce private properties into Javascript. But, its actual purpose is for name collision.

Unfortunately, however, they ended up being severely downgraded, and not private after all, because you can find them via reflection. Specifically, via the Object.getOwnPropertySymbols method and through proxies.

Every symbol value returned from Symbol() is unique. A symbol value may be used as an identifier for object properties; this is the data type's only purpose. (as per mozilla)

var Pet = (function() {
  var typeSymbol = Symbol('type');
  function Pet(type) {
    this[typeSymbol] = type;
  }
  Pet.prototype.getType = function(){
    return this[typeSymbol];
  }
  return Pet;
}());

var a = new Pet('dog');
console.log(a.getType()); // prints dog
a[Object.getOwnPropertySymbols(a)[0]] = "cat"
console.log(a.getType()); //prints cat
hashbytes
  • 769
  • 1
  • 8
  • 26
  • This is one possible use-case, though I don't think it was a driving force. It was more for dealing with different code sources overriding one another. – samanime Apr 02 '18 at 17:53