This is along the same lines as the question titled "Capturing Nashorn's Global Variables". I'm finding it very limiting not being able to intercept the assignment of variables to the global object.
For instance, say I eval the script "a = 10". Perhaps I want to call a listener to notify something that 'a' was added to the scope. The only way I could do this is to investigate the global object after the script is eval'd.
Or say i want to intercept an object being assigned to the global scope and substitute it for another; if it was using Bindings I could implement put, and delegate off to some other bindings:
public Object put(String name, Object value) {
//put a toStringed version of the object in scope
return delegate.put(name, value+"");
}
This way, when the code 'a=10' is evalled, it would put "10" in scope instead of 10.
It's handy having a Bindings interface to implement, but frustrating that I can't provide something like this implementation for the global object. ScriptObjectMirror is final, so I can't even overload this and hijack the subsequent call to the internal ScriptObject. Am I missing something?
So basically what you want to do is to intercept/trap assignments to arbitrary properties on some object. In your case, the global object.
Afaik, this was never really possible without some pretty hacky code indeed. A search for 'observables javascript' might help you with that, but be warned that you'll get into some muddy territory.
If this is meant for testing (as opposed to production code), a setTimeout / setInterval with some listener that periodically enumerates all properties of the global object and logs a warning if one was added might be good enough for you.
In the future, we'll have the Javascript Proxy standard to help us with this but I seriously doubt it is there yet in Nashorn. It's been a while since I worked with Nashorn but after the initial burst on the scene it has been quiet on the Nashorn front afaict...
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.
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'm working on an application framework written as an object literal and for the sake of simplicity I'd like to do two things:
Have the object available globally
Use the object name (as globally defined) for all references (vs. using this)
So, I've run some tests, done research, and am not finding any good reason NOT to take this approach. My question is - am I missing something? Perf tests actually seem to favor my method and from a logistical level I don't see any issues. Looking at other frameworks I've seen a mix, but I know that the this reference is revered by many programmers.
For reference...
A very minimal example of my approach:
var myobj = {
someVal: 'foo',
init: function(){
// Make myobj available globally
window.myobj = myobj;
// Fire off a method
myobj.doStuff();
},
doStuff: function(){
// Just print out the contents...
console.log(myobj.someVal);
}
}
myobj.init();
Note the references are all to the global, not this.
Like I said, I've seen a mix of this, I guess I just would like to know if this could cause issues in the long-run or if this a much ado about nothing.
As far as limitations go, the first thing that comes to mind is that you could only have one instance of this object. Trying to initialize a new one would wipe out the object.
Another reason for using this rather than a global variable name is that this will point to the correct object even if the name of the variable changes.
If you really want this to be a "create once" global object whose name never changes then this technique isn't technically wrong. But it won't be able to be used in any other situation. It is probably wiser to consider writing code that will be more adaptable if the requirements change (for instance if you use a library that causes a naming conflict with the chosen variable name)
Using this lets you be flexible in renaming the variable and passing it in different contexts without worrying about tracking variable names. It also will make it easy to change if naming conflicts arise.
I've been reading this book "Javascript Enlightenment" by Cody Lindley. On page 82 he states: "Being explicit (e.g. window.alert() v.s. alert()) costs a little bit more with regards to performance. It's faster if you rely on the scope chain alone and avoid explicitly referencing the head object even if you know the property you want is contained in the global scope."
I am kind of curious why this is. I would think that it would be the opposite, because the Javascript interpreter could just skip checking the scope and find it directly. I just don't see how it is beneficial to not specify the exact address of something.
I mean, I know I am not going to want to type window.whatever() every time I want to use something contained in the global scope and I think it is great that it is faster to not specify. Just not sure why.
Just one of those "want to know" things.
The interpreter always has to use the scope chain. When you write window.alert() it has to walk its way up the scope chain to find the value of window -- you might have a local variable named window that shadows the one in the head, so it can't assume this is the global object.
If JavaScript had a syntax to explicitly denote the top-level context, that would be faster. But it doesn't.
I was looking over the code for qunit.
My question is why would you want to attach the qunit object via property to window object.
Here is the link to the file. Look at line 11.
If I look at a unit test run using firebug you can see it is a property of window.
[edit]
Additional: Is there a specific reference for best practice for declaring things in specific namespaces?
All global objects (functions, variables, etc) are just children of window, it's the default context.
For example: window.jQuery or window.$
It may be easier to think of it this way...where else would you put them? When you're doing something this general, best (or at least easiest) to stick them in the default place. If you're doing something complex with lots of functions, objects, etc...best to put them in a namespace or within an object. For example all of jQuery's code is under jQuery, not littered in the root of the DOM like window.ajax, instead it's jQuery.ajax.
This is much neater, but perhaps overkill when you're dealing with a few items, but it's a good idea to make sure they are unique if this is the case...which qunit does, by prefixing their objects with qunit-
Attaching globals as properties of window is bad practice. All globals should be declared using var. Here's my reasons:
It makes static analysis of source code much harder. It is impossible to tell from looking at a script which globals will be declared and when. Undeclared globals will create ReferenceErrors if they're used. Using var means JavaScript's hoisting takes effect, and mitigates this problem.
Globals made this way are fundamentally different, and there is no easy way for your code to detect this. The biggest difference is the absence of [[DontDelete]] on globals made this way, which means you can delete your global variables. This is silly.
It will tempt you to declare your globals from outside the global scope. This is magic, and bad magic at that. Don't do it.
As far as I'm concerned, the fact that window.x = 1 creates a global variable named x is an interesting curiosity of JavaScript, but should not be used nor replied upon. There are, however, good reasons to use properties of window, since it's an object like any other (more or less). In these cases, you should use the full name, e.g. window.onload instead of just onload.