Jotsite Water Cooler Area




Post a New Topic

Show Recent Topics 

JavaScript object context


OK, when I pass a member function to a callback I expect the "this" context to switch to the class containing that member function. I just tried to perform the most basic encapsulation strategy with a callback in a class, and Venkman (the debugger that comes with Firefox) tells me in the middle of the callback that the context is still the span that made the callback. Is this weird or is it just me? Does it behave this way in other languages and I haven't been paying enough attention?

Sonny
September 28, 2005 (22:04)


Thinking "this" through: the "this" reference/pointer (from here on r/p) for most languages changes at compile/link (c/l) time. Whenever "this" is indicated or implied in the code the c/l replaces "this" r/p with a calculated r/p specific for that object. JavaScript on the other hand never gets compiled and so "this" isn't a true per-instance r/p but instead some runtime instance context is kept. Unfortunately this alternate scheme fails when calling back member functions of another class.

Here's a small part of my failing system:
In a script block
<script>
function popupMenu(attachTo)
{
function showMenu(xval, yval)
{
alert("clicked");
}
this.show = showMenu;
}
var pum = new popupMenu(window.document.getElementById("sp1"));
</script>

And in the html
<span id="sp1" onclick=pum.show>ClickMe</span>

The JavaScript interpretor believes onclick's callback stays in the span's context while in a compiled language pum would have a "this" reference to the popupMenu instance.

Sonny
September 29, 2005 (13:38)


Just a mistake on my part regarding type safety. It seems the callback mentioned in my code creates a reference to a function, and JavaScript doesn't know to change the context. Using onclick="pum.show();" instead provides the correct context because it is "eval"uated as JavaScript rather than assumed to be an unclassed function reference.

Sonny
September 29, 2005 (14:32)


Just to preface, I am not an expert on JavaScript. However, if we just speak to Object Oriented programming.... let's be specific (C++) .... the "this" pointer is a dynamic pointer. "this" is computed during runtime and inserted into the parameters as needed. For those coming from static typed languages, this can be confusing as hell. "this" refers to the handle of the current instantiated object.

Sonny, I think you need to step back and realize that the "this" pointer that you are trying to pass is dynamic and likely points to some place on the current stack.

Hoang
October 05, 2005 (04:53)


Don't think so, compiled objects at runtime already have a good sense where their jumptables start. However objects in the JavaScript sense have no precalculated jumptable, so "this" points to whatever context we're in at the moment.

In my case when in a JavaScript class (call it A), another object's (B's) handlers are set to "this->fn()". In a compiled language the compiler/linker (not sure which one) would know that "this" needed to be converted immediately into something in A's jumptable -- this is the meaning I'm used to and my intention. When the same code is interpreted by JavaScript in B's code "this" refers to B rather than A when it was configured -- totally inappropriate where there is no way to point to A's function.

Sonny
October 12, 2005 (12:50)


Just a couple more thoughts:

Languages that are typed versus untyped has some relevance to this discussion, though I think we need to go deeper where it's more a matter of when those types are resolved. I don't know which behavior VBScript (untyped, most familiar with Microsoft's ASP pages version) would follow -- don't even remember using objects so extensively in my VBScript projects.

I think the key is when the "this" token is resolved into a member function -- how do you reference the running object instance's other functions? The classical "this" idea is based on relative addresses where the complete address is configured at runtime, but the relative address of the object's members (the reverse link back to the jumptable) is determined during compile/link. In JavaScript setting "this->fn()" as a handler doesn't get evaluated while in the context of the current handler configuring class, it gets resolved when the code is encountered.

Sonny
October 12, 2005 (13:31)


compiled languages: resolving of symbols, think 'linking phase'.

dynamic languages (scripting): resolving of symbols, think 'interpreter'.

Hoang
October 14, 2005 (08:21)


Resolved:

http://w3future.com/html/stories/callbacks.xml describes the problem more succinctly as well as provides a little trick that makes it so the callbacks (event handlers more specifically) can be incorporated into classes while retaining some sense of "this".

Sonny
December 18, 2005 (08:59)


Can't seem to convince myself why this works, so here is my interpretation of what is happening:

During the initial load of the script, the class is defined as are all the methods therein. The "this" pointer however is run-time configured so that callbacks depending on "this" fail. Other things though like the "var me=this" pointer defined and used within the class itself without a "this" scope ("this.me" in this case) are visible during initial definition only, and drop out of scope at the end bracket for the class. Does the interpretation make sense?

Sonny
December 18, 2005 (11:07)


Can't seem to convince myself why this works, so here is my interpretation of what is happening:

During the initial load of the script, the class is defined as are all the methods therein. The "this" pointer however is run-time configured so that callbacks depending on "this" fail. Other things though like the "var me=this" pointer defined and used within the class itself without a "this" scope ("this.me" in this case) are visible during initial definition only, and drop out of scope at the end bracket for the class. Does the interpretation make sense?

Sonny
December 18, 2005 (13:59)




Write a Reply