We know what the global symbol registry (GSR) is.
It is global and I can access its data with Symbol.for and Symbol.keyFor.
window is global and I can access it with its name.
Is there a similar mechanism for the GSR or is it a private global registry?
The window object is very different from the GSR (and less "global" of course).
No, the GSR is not represented as an object that is accessible to JS code, with properties for key-value pairs or so (or as a Map maybe). It cannot be enumerated, if that is what you are looking for. The only ways to access it are Symbol.for and Symbol.keyFor, which suffices to expose the bijective property of the relation.
This was probably (read: my speculation) done to simplify the implementation. The GSR needs to handle symbol references weakly, they should get garbage-collected when all realms that used them are terminated. Also, the multiple realms that access it might run in different threads, which adds complexity. Exposing the mapping directly to code might introduce race conditions (similar to the reason why WeakMaps are not enumerable).
Related
In web environment think this code:
window.alert('foo'); //code1
alert('foo'); //code2
Why code2 is higher than code1 in performance? Why does this happened?
First, remember that many globals (including all of the traditional predefined globals) are properties of the global object, and that on browsers that global object is the window object. window isn't special, it's just a predefined global that refers to the global object. alert is also a predefined global.
window.alert(...) is slower than alert(...) because in window.alert(...) the JavaScript engine first has to:
Go look up the identifier window, which it ultimately finds as a property of the global object, then
Look up alert in that object's properties, then
Call the function it found
In alert(...), it only has to:
Go look up the identifier alert, which it ultimately finds as a property of the global object, then
Call the function it found
So instead of looking for two things, it only has to look for one.
Less work = faster performance.
Having said that, two observations:
The speed with which you show an alert is...not usually important. :-) alert does, after all, seize up the JavaScript engine until the user dismisses it.
Even with something that doesn't seize up the JavaScript engine, the difference between window.xyz(...) and xyz(...) will be trivially small in most cases. Typically you see window.xyz(...) for other reasons (such as some other xyz being in scope when you want to access the global one). (I'm not saying they're good reasons; typically you can avoid that, and of course one tries to avoid globals wherever possible anyway...)
If performance calling a global function matters (by definition, this means you're calling it a lot), you probably don't want to use the global reference to it anyway; grab a local reference to it in your inner scope (var f = theGlobalFunction;) and then use f(); to call it repeatedly. This avoids both lexical environment traversal and lookup on the global object. And again: Only matters in very rare cases; don't do it until/unless you've identified an observable performance problem and narrowed it down to the global function call. :-)
The time for that first lookup (the global) depends on how deeply nested the code is (and thus how many lexical environment objects need searching before the global one is reached) and how many properties the global object has. The second part, looking up the property, is only dependent on the second one. A truly hideously massive mass of globals (such as is created if you use ids on lots of elements, since those get added as automatic globals) can conceivably slow down global lookup time.
Is it possible to check if a symbol is available in global registory?
What I do:
global[Symbol.for('childoftheelderblood')] = true;
//In another file/window/universe
if(!global[Symbol.for('childoftheelderblood')]) console.error('Sorry, but your Ciri is in another universe');
What if global is not available in the parallel universe? Only symbols are cross-dimensional and universal. Can I somehow check if a symbol has been created in the global registry without actually creating it like Symbol.for does.
Is it possible to check if a symbol is available in global registry?
No. Symbols in the global registry are not "created", they're fetched from it. You can imagine that the registry already contains all possible symbols - though of course they are created lazily (as needed) in the real implementation.
The global symbol registry is not a communication channel1. It cannot be mutated. All it does is provide access to common symbols so that they can be used as properties of shared objects.
If you have multiple realms and you want to pass the childoftheelderblood = true bit between them, you need to do so explicitly using shared buffers, storage, or messaging as provided by your environment.
1: If it was, that would be a huge security hole which enables leaking information
are there any specific disadvantages of defining a global function, as there are for defining global variables?
We are trying to downsize our custom JS file, and quite a bit of code is being used across functionalities.
Namespace collisions are one big issue. If you create a global function, and accidentally use the same name as another global function, you will overwrite that function, which may cause your application to break.
Bear in mind that all global variables are actually properties of the window object. If you accidentally overwrite a built-in property of window, you might produce some really odd glitches that can be hard to track down.
Another reason is just general cleanliness/organization. If you write a dozen functions to do operations on strings, you might want to put them all on an object stringOps, so that you've got them in one place.
The main danger with global references are that you will step on someone elses reference or vice versa. This can make testing extremely difficult as you may have introduced a large dose of non-determinism.
For instance say you define Global.PI as 3.14159 and your functions which ref that work fine, until a user loads a page with a library that defines Global.PI as 'Lemon', now your functions work not quite as expected.
The project I work on has global references due to the strucutre of our application.
To alleviate some of these issues we will attach a single object to window (window.yourObjHere) and place our global references within that object.
The only advantage to Globals are that some things simply can't be done without them. We have an eventBus that must message over seperate AngularJS applications. As the AngularJS native eventBus is per application, we have to register each application on our GLobal object in order to keep track of where messages should go etc. Whenver possible avoid using Globals but there are simply some things which can't be done without them. Just be careful and limit your Global footprint.
The disadvantages are as poeple ahve outlined (basically no namespacing meaning functions/variables can be overwritten) but you could get around this by declaring a global object which has all you need in it - and you can add things to it 'on the fly' :
GLOBAL_myObject = {
variableOne: 1,
variableTwo: "A atring",
getThisAndThat: function(p1,p2) {
//do some stuff
return p1 * p2; /or somthing
}
};
So refer to all your own variables as a property of that object:
alert(GLOBAL_myObject.variableOne);
GLOBAL_myObject.getThisAndThat(1,2);
Effectively you're just namespacing the variables.
to add more to the global GLOBAL_myObject you can just declare it ..
GLOBAL_myObject.anotherThing=1965; // what a year!
I have a big object defined in the global scope called global. I would like to dynamically find all the referenced properties under my variable global. That is, all the properties that were accessed during the execution of the code.
I want to do static code analysis to extract all the referenced properties under my variable. I can search for these patterns: global.PROPERTY_NAME AND global[PROPERTY_NAM]. However, what about the complicated cases like these ones
var tmp="PROPERTY_NAME";
global[tmp]
OR
var tmp=global;
tmp.PROPERTY_NAME
and the other ones?
I don't want to get all the variable's properties. I only want a list of the referenced ONES!! the properties that were referenced in my source code only
After your edit:
What you're looking for is JavaScript Proxy objects. Here is a tutorial on how to do this using them.
Proxy objects let you wrap an object and execute a method whenever its properties are accessed. Unfortunately as it currently stands they are not widely supported.
This is currently only way in JavaScript to accomplish this without changing your original global object.
You can turn them on in Chrome by enabling experimental JavaScript in the about:flags tab.
Before your edit:
The feature you're looking for is called reflection, JavaScript supports it well and natively
Here is some code that iterates through an object and gets its properties
for(var prop in global){
if(global.hasOwnProperty(prop)){ //this is to only get its properties and not its prototype's
alert(prop+" => "+global[prop]);
}
}
This is fairly cross-browser. More modern browsers allow you to do this in simpler ways like Object.keys(global) which returns an array containing all its enumerable properties, or Object.getOwnPropertyNames(global) which returns both enumerable and not-enumerable properties.
Due to the dynamic nature of JavaScript you won't achieve that with static code analysis. Think about cases like this:
var prop = document.getElementById('prop').value;
global[prop];
Impossible. The alternative, dynamic analysis, would mean that you modify your global object to log access to its properties, then run the code. This is easily possible in JavaScript but it won't help you either because how would you assure that you have covered every possible access? Especially in a 5 MB JavaScript, there are most likely edge cases that you will oversee.
So, if you can't narrow down your requirement, it won't be possible.
Say I instantiate a large object with var and new. After I'm done with it, can I "free" it by setting it to null? Is this something Javascript GCs look for?
The garbage collection is interested in objects, that are not referenced by ANY other object. So make sure there are no references left anywhere in your application (Arrays etc.)
You can break the reference by setting the variable to null, but it doesn't break any other references.
All references need to be broken individually before the object can be GC'd.
So yes, if the only reference to the object that is held by that variable, then setting it to null will free it for eventual GC.
as am not i am stated, you'll need to break all references in order for a variable to be eligible for garbage collection. This can be a difficult task if you can't track down that last reference to a specific Object, so use the tools available to you for this task. Personally I use the Chrome's Heap Profiler which you can read about in the chrome docs.
Also, note that only non-primitive types are passed by reference (and therefore only non-primitive types can be GC'd).