Get a user-defined object in Javascript - javascript

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.)

Related

Why call method of window object explicitly, performance will be lower than inexplicitly

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.

How to get pointer to a local variable in Javascript?

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.

Accessing/Intercepting Nashorn's Global Object Variables

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...

Listen for window events or attach objects to window

I have an object, which I need to control from another object.
What's a better practice and why?
Reference the object by window.object = this in it's constructor and then call window.object.method() from the other one
or
Start listening like $(window).on 'objectEvent' and triggering the event from the other object like $(window).trigger('objectEvent')?
I am currently using the second approach, but I'm wondering, whether it's the right one.
The second approach is the least bad. You want to avoid polluting the global namespace, ie: adding properties to window.
In the second case you are adding listeners to it, which isn't that bad if you namespace event names, but the best option would be to use an intermediary object and implement the Pub/Sub pattern, so both objects interact b/w themselves through it.

Does this create a circular reference in javascript?

In Determing if a SQL select returns an empty set asynchronously? I ended up trying to use an object's method's as an event handler. Using the normal "this" of the object doesn't correspond to the method's object in the context of an event handler (why, not sure, beyond my current simplistic understanding of javascript, my guess is due to scoping of variable names?).
As I mentioned in my previous Q, from http://w3future.com/html/stories/callbacks.xml, their solution is to basically have each object provide a "var me = this" variable. My question is, does this create a circular reference that will prevent the object from being garbage collected?
If so, is there a better way to accomplish the task?
thanks.
Yes, that will create a circular reference.
However, it won't cause any problems.
Modern Javascript garbage collectors can handle circular references perfectly well. (except, in IE6, for references crossing between DOM and user objects)
If s and everything that references it either leaves reachable scope or is manually deleted, then it will get garbage collected. If you delete s but statement.executeAsync still has reference to the callbacks, the references to me will stay around too.
delete s;
s; //undefined
//This will still contain the function reference
statement.executeAsync.handleResult;
delete statement; //Now s and me should be garbage collected
If you just clear each handler individually instead of the statement object, that would work too. Assuming you can reach each callback individually.
delete statement.executeAsync.handleResult;
delete statement.executeAsync.handleError;
delete statement.executeAsync.handleCompletion;
This also depends on how executeAsync is implemented. If the internal implementation doesn't store the callbacks in a scope that lives past the final callback, then it would get cleaned up with you deleted s

Categories