23
var sym = Symbol();

is window['sym'] which is already global scope.

But MDN says:

The above syntax using the Symbol() function will not create a global symbol that is available in your whole codebase. To create symbols available across files and in a global scope-like environment, use the methods Symbol.for() and Symbol.keyFor() to set and retrieve symbols from the global symbol registry.

sym is already in global scope in a browser, with above declaration syntax.

What is global symbol registry?

Each html document is tied with window object.

So, In a browser world, How does this scope of symbol availability across files/realms different from global scope(window object)?

Pacerier
  • 86,231
  • 106
  • 366
  • 634
overexchange
  • 15,768
  • 30
  • 152
  • 347
  • So what's your question, why creating a global variable makes it a global variable, even when the value of the global variable is a symbol ? – adeneo Aug 08 '15 at 18:18
  • @overexchange What do you mean by "actual value"? It's super unclear what you're expecting. `sym` is the value, there is nothing else to show. – loganfsmyth Aug 08 '15 at 18:49
  • loganfsmyth, that was with reference to some linked question, Ignore it. – overexchange Aug 09 '15 at 00:39
  • See also [Symbol.for(string) in ECMAScript 6](http://stackoverflow.com/q/30984858/1048572) – Bergi Aug 09 '15 at 14:09

3 Answers3

23
var sym = Symbol();

is creating a new property sym in dictionary(window), which is in global scope, where value can be accessed as window['sym'].

Well, no. It does create a symbol and assigns it to a local variable named sym. Only if you are executing this code in the global scope (which you usually wouldn't, for modularity) it does create a property on the global object of your realm (js environment). Notice that this global object is not always window like in web pages, it depends on your environment.

What is global symbol registry?

It's a registry (think: dictionary) for symbols that you can access via a string key. And "global" does in this case mean even more global than a global scope, the global symbol registry does span all realms of your engine. In a browser, the web page, an iframe, and web worker would all have their own realm with own global objects, but they could share symbols via this global registry.

And this sharing is exactly the purpose. If you'd otherwise put

var sym1 = Symbol("shared");

var sym2 = Symbol("shared");

in two places, then sym1 !== sym2. If you've got a shared object, using the symbols as property keys would create two different properties. If however you do

var sym1 = Symbol.for("shared");

var sym2 = Symbol.for("shared");

then sym1 === sym2 and when you use it you'll always get the same property.

See also Crossing realms with symbols on 2ality and Symbols and why they're awesome for more examples, including the well-known symbols which are similarly global.

TmTron
  • 17,012
  • 10
  • 94
  • 142
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Is GlobalSymbolRegistry(GSR) physically different from `window` object? As JS engine of a browser maintains `window` object, Who maintains GSR? – overexchange Aug 08 '15 at 19:04
  • 1
    @overexchange: Yes, it's very different. It only contains strings as registry keys, and only symbols as values. The global object contains all kinds of properties. The global symbol registry is maintained by the JS engine. Notice that a JS engine does maintain *multiple* global environments/scopes/objects/`window`s; that's why is said the GSR is "more global". – Bergi Aug 08 '15 at 19:13
  • Any article that talks more on multiple global_environments/scopes/objects/`window`s that is maintained by JS engine? – overexchange Aug 09 '15 at 01:19
  • @overexchange: I didn't find anything specific, it's a well known fact that each web page has it's own global environment, e.g. [here](http://stackoverflow.com/a/4857969/1048572). Except for the obvious security reasons, this is so that each page is stand-alone, and e.g. can be run in its own browser thread. The HTML5 spec also refers to [global environments](http://www.w3.org/TR/html5/infrastructure.html#javascript-global-environment) when it does define the [javascript processing model](http://www.w3.org/TR/html5/webappapis.html#definitions-0). – Bergi Aug 09 '15 at 14:06
  • But I got one example from your [reference](http://2ality.com/2014/12/es6-symbols.html#crossing-realms-with-symbols). What more can I ask? – overexchange May 12 '18 at 16:57
6

The global symbol registry is just a convenient global repository for symbol instances. You could implement one yourself if you wanted to, but having such a repository built-in means that the runtime can use it as a place to publish symbol instances that have particular meaning for a given context.

In your own application, you can decide that some types of objects will have certain properties accessible via some symbol. All your code can find those symbols via Symbol.for():

var SPECIAL_PROPERTY = Symbol.for("mySpecialProperty");
// ...
var specialVal = someObject[SPECIAL_PROPERTY];

Because the registry is global, that works regardless of scope or compilation unit.

By making the registry part of the runtime, an environment like Node.js can use the symbol mechanism to extend objects without fear of causing problems for legacy code. Like, if Node wanted to make it such that you could find out how much memory an object used, they could invent a symbol, put it in the registry, and document the registry key. Any code could then use that:

var objectSize = myObject[Symbol.for("memory_use")];

(That's totally made up; it might make no sense at all for Node to do that particular thing.) Because of the way symbols work as property keys, code that doesn't know about that won't experience any weird issues should the objects it manipulates suddenly start carrying around that extra property.

(Of course, the namespace of the symbol registry itself is just a namespace, so collisions would have to be dealt with there in pretty much exactly the same way we deal with name collisions in the window object.)

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • Global scope is at `window` object level. If a single html file includes multiple .js files thru script tag. Environment created by multiple .js files comes under same single `window` object. Am I correct? When you say across files(whole codebase), which scope are we talking about? Am still not clear. – overexchange Aug 08 '15 at 18:33
  • @overexchange it's at `window` object level *in a browser*. There are other JavaScript environments that have no `window` object. But yes, all JavaScript code in the context of a web page have access to the same `window` object. The scope of the global symbol registry is simply the same scope as that of the global `Symbol()` function itself. – Pointy Aug 08 '15 at 18:48
  • 1
    Is *global symbol registry*(GSR) part of JS engine that is physically different from `window` object? If GSR is at same scope of `window` object, then why do we require GSR? – overexchange Aug 08 '15 at 18:56
  • Also, in most modular JS code (including Node), the top-level scope of the file is the module scope, not the global scope, so your `var sym` example would not be global. – loganfsmyth Aug 08 '15 at 18:56
1

Global symbol registry exists across all iframes in a window. (As symbols can't be passed across workers, there's no observable concept of it being identical across workers, barring the existence of sidechannel inspections, eg by memory probing.)

<script>
document.head.appendChild(document.createElement('iframe'))
.src=`javascript:
  alert(parent.Symbol===Symbol) /*false*/
  ,alert(parent.Symbol.for('a') === Symbol.for('a')) //true
`
</script>

Symbol.for is not much different from implementing your own cache using an object reference. It's merely in-built and thus more convenient. Instead of Symbol.for('a'), you can simply do:

obj['a']? obj['a'] : obj['a'] = Symbol()

.and maintain a ref to obj.

In fact, since javascript does not provide an API to remove symbols in the global registry, its beneficial to do it the manual-caching way if you need to manually manage the memory of the registry.

itamar
  • 3,837
  • 5
  • 35
  • 60
Pacerier
  • 86,231
  • 106
  • 366
  • 634