Let say I know that a variable is called "myVar", it is declared in a self calling function
(function (){
var myVar=0;
setInterval(function(){
console.log(myVar++);
}, 3000);
})();
But I don't know where this function is called, and don't want to reverse engineer tons of JS. I want to find a reference to this variable so I can display it in console something like window.rootObject.subObject.myVar . I tried to make a function that does recursive seek for key from the window object, but it does a stackoverflow, certainly because of circular references (an object contain reference to its containing object).
Is there any simple way to find where is this object ?
Edit : the original question was about finding a var in global space having just its name, without knowing if it was descendent of window object or stored in EnvironementRecord. The sample code I provided was misleading, so I edited the question and accepted an answer to make it usefull.
myVar in your updated example doesn't "belong" to any object you can get a reference to. In specification terms, it belongs to the EnvironmentRecord for the variable environment of the execution context for the call to the anonymous function, but there's no way for you to get a direct access to that object (which may or may not literally exist at runtime at all, depending on how the JavaScript engine being used is implemented).
You seem to believe that all objects (even specification-only objects like environment records) are in a tree and are acessible following a path of references from some root object and so are "discoverable" somehow in code. That's understandable, but it's not the case. Certainly the JavaScript engine has trees like that for garbage collection purposes (for objects that actually get created at runtime), but no, there's no root from which everything can be discovered that you can access in code.
Locally scoped variables really are locally scoped. They are not accessible outside that scope at all. They are not properties that can be accessed through the window object.
If you want to debug code using the variable, set a breakpoint (e.g. by adding a debugger statement) inside the function to which the variable is scoped.
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.
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...
I know in node, every module gets an local scope and variable defined within one module won't escape to the global unless explicitly exported.
What I want to know is when I declare a variable in one module file as the following, what's the global object this variable defined on?
var obj = {};
// In browser, this is defined on window.obj
// How about in the node?
There is one statement that global is the object used as the local global scope, however the following test code fails:
a = 1
console.log global.a
// undefined
So what is the global variable for a module?
There is in fact a global object in node; it's simply called global. You can assign properties to it and access those properties just like any other object, and you can do it across modules. However, directly accessing it (global.foo=bar in one module, baz=global.foo in another) is the only way to access it. Unqualified variable names never automatically resolve to its properties the way that, say, an unqualified variable name in a browser environment would resolve to window.somethingOrOther. In node, every module is conceptually wrapped inside an immediate function call, so unqualified names represent local variables and have module-level scope.
edit again I'm just about ready to conclude that, in a Node module, you can't get a reference to the global object. You really shouldn't need to; that's kind-of the whole point of the module mechanism, I think. You import what you need and export what you choose.
Whether there even is a global object in Node is an interesting question, I guess. I know that in Rhino, there definitely is; there's no implicit wrapper function around code fed to Rhino from the Java container. Via the Java ScriptEngine mechanism (and presumably from Mozilla APIs in "naked" Rhino) there are ways of pushing symbols into the global context to make them visible to JavaScript as global object properties.
wow this got complicated well things seem to be on the move in the Node.js world. What I wrote above was true for Node 0.6.2, but in the 0.9.0-pre build I just did there is indeed an object called "global" that behaves more or less like the global object in a browser.
The stuff below applies to browsers and Rhino and other contexts like that
You can use this in the global context. If you need a name, you can give it one.
var global = this;
var obj = "Hi!";
global.obj = "Bye"; // sets "obj"
A (somewhat) common idiom is to wrap your code in a function, to protect the global namespace.
(function( global ) {
// everything
})( this );
Caveat: I'm not a Node person so there may be some emerging idiom in that culture.
edit — it occurs to me that if Node really does wrap code from files it evaluates in a function, and it doesn't pass this into it from the global context, then there's no way to "find" it, I don't think. If you use "use strict" (and you should), it doesn't matter, because you can't really mess with the global context anyway.
JavaScript: The Good Parts defines these kinds of declarations as bad:
foo = value;
The book says "JavaScript’s policy of making forgotten variables global creates
bugs that can be very difficult to find."
What are some of the problems of these implied global variables other than the usual dangers of typical global variables?
As discussed in the comments on this answer, setting certain values can have unexpected consequences.
In Javascript, this is more likely because setting a global variable actually means setting a property of the window object. For instance:
function foo (input) {
top = 45;
return top * input;
}
foo(5);
This returns NaN because you can't set window.top and multiplying a window object doesn't work. Changing it to var top = 45 works.
Other values that you can't change include document. Furthermore, there are other global variables that, when set, do exciting things. For instance, setting window.status updates the browser's status bar value and window.location goes to a new location.
Finally, if you update some values, you may lose some functionality. If, for instance, you set window.frames to a string, for instance, you can't use window.frames[0] to access a frame.
Global variable make it very difficult to isolate your code, and to reuse it in new contexts.
Point #1:
If you have a Javascript object that relies on a global var. you will not be able to create several instances of this object within your app because each instance will change the value of the global thereby overwriting data the was previously written by the another instance.
(Unless of course this variable holds a value that is common to all instances - but more often than not you'll discover that such an assumption is wrong).
Point #2:
Globals make it hard to take existing pieces of code and reuse them in new apps. Suppose you have a set of functions defined in one file and you want to use them in some other file (in another app). So you extract them to a new file and have that file included in the new app. If these function rely on a global your 2nd app will fail at runtime because the global variable is not there. The dependency on globals is not visible in the code so forgetting these variables (when moving functions to new files) is a likely danger.
They're global variables, so yes, all of the "usual dangers" apply. The main thing that distinguishes them from global variables in other languages is that:
You don't explicitly declare them in a global scope. If you mistakenly omit var in a variable declaration, you've accidentally declared a global variable. JavaScript makes it a little too easy to unintentionally declare global variables; contrast this with Scheme, which raises an error if a variable is not defined in the global scope.
Global variables, at least in the browser, are aliased by window[variable_name]. This is potentially worrisome. For example, some of your code might access window['foo'] (with the intention of accessing a global variable). Then, if you accidentally type foo instead of var foo elsewhere in the program, you have declared a reference to window['foo'], which you meant to keep separate.
One issue is that you may be trampling on already defined variables and not know it, causing weird side effects in other parts of the code that can be a bear to track down.
Another is that it is just sloppy code. You should not be creating variable with more scope than they need since at the very least it keeps more variables in memory and at worst it can create data scenarios you didn't intend.
The bottom line is that when you do that you don't know for sure that you are not messing up other functions that use a global variable of the same name. Sometimes it isn't even your fault, a lazy programmer of another plugin left something global that was meant to have scope inside of a function. So it is a very practical safeguard for writing better and less buggy code.
The problems of typical global variables is that they are, well, global - there is no scope to enclose them, and any code that you are executing / interacting with (such as a library that you call down the road) could modify the variable without a warning.
However, these problems are compounded in Javascript by two things:
You can define a global variable anywhere - the only requirement for that is to forget the var keyword.
It is extremely easy to define a global variable when you had no intent to do so. That is the problem that "implied" globals have over "typical" globals - you will create them without even knowing you did.
In a reasonably-designed language that includes truly global variables (ok, so not that reasonably-designed), you would have a limited handful of places to define globals, and it would require a special keyword to do so.
I have a script which creates a user-defined object like this:
obj = new Tree();
This object is always present and interacting with the user.
I want to create a button on the page which, if pressed, should retrieve this object, make some changes to the object and call some methods.
If this were a DOM object, I could have used any of getElementById() or getElementByTagName() etc. However, this object is created in the script and I need to access it in another part on user intervention. Further, making the object global is not an option. Does anybody know how it may be done?
You can attach objects to window if you are defining them inside a different scope than the one you want. This should make it "global". Although I highly suggest fixing your scoping so that var obj exists where it needs to, and not anywhere else.
window.myObj = new Tree();
You will need to make the object accessible from some part of the event handling function. So while making the object itself global is not an option (which is a good move), presumably there's some top-level object which is global to the page for your application? Something like a namespace object, or an OurPageScript object, something like that? In that case, setting the tree as a property of this object will allow for it to be dereferenced later by the event handlers.
If you absolutely cannot have any variables that are accessible from anywhere across the page, things get more tricky. In that case, you will need by definition to provide the event handlers with a reference to your object (because they won't be able to get it themselves). The only way I can think of to do this is to rewrite the handlers every time the object changes; setting them to a closure that includes the object, and invokes the actual handler with this object as a parameter.
A middle ground might be to give the appearance of a global variable by declaring that all event handlers will be invoked in a closure environment where var_tree is defined. That way you wouldn't need to actually mutate the handlers, just repackage them in an appropriate closure whenever the object changed.
(I presume your question was solely about getting access to the object; once the handlers have this, they can modify it and call methods with no further gotchas.)