Samstag, September 16, 2006

Help on this - Scope in JavaScript

I really do not often link up to other postings on the web but in this case I have to!

Thanks to Mike West and his article "Scope in JavaScript" published at http://digital-web.com/articles/scope_in_javascript/.

I really like this article and I learned from it. It's the same story all the time: When you understand, things get easier and seems to be simpler.

If you've read my book you have noticed that I fell over the context problem when attaching JavaScript function to events. The solution I suggested was to implement a inner method that gets a usable context and there are some tricks implemented to find the right context by analyzing the target of the event.

Now, with the bind function I can reduce this overhead and we have right context right from the start.

It's not as easy as it seems

My first idea was to include the bind functionality into jcl.AttachEvent the cross browser compatible helper around attachEvent() or addEventListener() to register events but I had a lot of problems until I found that the DetachEvent is not working any more as expected.

The problem is that when using the bind() function you get a reference to a new, not the original passed function. Because you have no reference to this new function you can not use it when calling jcl.DetachEvent. If you want to detach the handler from the event you have to pass the same reference. Calling obj.detachEvent("onclick", handler.bind(obj)) will never work as expected.

... but don't give up

After some analyzing I found that most of the events are using functions that never get detached. The "on___" functions of the behavior object are automatically attached to the corresponding events but will never get detached until the page gets reloaded. These functions are now executed in the context of the bound object and it gets really access other members of the behavior.

The other situations that benefits a lot from the .bind function is when registering a timer event. Here a detach will never happen because the timer event gets canceled by using clearTimeout and you have to pass the timer, not the function reference. In many cases we need to call a method of a specific element like:

this._scrollTimer = window.setTimeout("document.getElementById('"
  + this.id + "').scrollend()", 100);

By using the bind function it looks like this:

this._scrollTimer = window.setTimeout(this.scrollend.bind(this), 100);

The other advantage you can see here is that a function reference can be passed to setTimeout which is faster than a string that gets evaluated.

New version is online

The web site was updated to this new version including a lot of new visual controls and some housekeeping bug fixes. - Get a copy from http://www.mathertel.de/Downloads/Start_AJAX.aspx or from the download area.

Keine Kommentare: