<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>TBNL &#187; closure</title>
	<atom:link href="http://www.tibobeijen.nl/blog/tag/closure/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.tibobeijen.nl</link>
	<description>...another view on the web and how it's built</description>
	<lastBuildDate>Wed, 06 Jul 2011 19:28:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Taming the Javascript event scope: Closures</title>
		<link>http://www.tibobeijen.nl/blog/2009/07/27/taming-the-javascript-event-scope-closures/</link>
		<comments>http://www.tibobeijen.nl/blog/2009/07/27/taming-the-javascript-event-scope-closures/#comments</comments>
		<pubDate>Mon, 27 Jul 2009 13:52:44 +0000</pubDate>
		<dc:creator>Tibo Beijen</dc:creator>
				<category><![CDATA[miscellaneous]]></category>
		<category><![CDATA[closure]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://www.tibobeijen.nl/?p=459</guid>
		<description><![CDATA[When doing client-side developing there are times that jQuery&#8217;s get-this-do-that nature doesn&#8217;t provide all that is needed. For more complex applications I usually find myself creating javascript objects that &#8216;control&#8217; a specific part of the page&#8217;s interaction. In the objects the application&#8217;s state is tracked, references to other objects (could be relevant DOM nodes) are [...]]]></description>
			<content:encoded><![CDATA[<p>When doing client-side developing there are times that jQuery&#8217;s get-this-do-that nature doesn&#8217;t provide all that is needed. For more complex applications I usually find myself creating javascript objects that &#8216;control&#8217; a specific part of the page&#8217;s interaction. In the objects the application&#8217;s state is tracked, references to other objects (could be relevant DOM nodes) are stored and event handlers are set.</p>
<p>One of the problems typically encountered when dealing with javascript event handlers is that they have their own take on the &#8216;this&#8217; keyword. Closures to the rescue.<br />
<span id="more-459"></span><br />
A simple (and rather useless) example:</p>
<p>html:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>script language<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;javascript&quot;</span> type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>
$<span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">ready</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#scope div'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">each</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>idx<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">var</span> btnController <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> controllerExample<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span>idx<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;/</span>head<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;</span>body<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;</span>div id<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;scope&quot;</span><span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>div<span style="color: #339933;">&gt;</span>
        <span style="color: #339933;">&lt;</span>p<span style="color: #339933;">&gt;&lt;/</span>p<span style="color: #339933;">&gt;</span>
        <span style="color: #339933;">&lt;</span>input type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;button&quot;</span> value<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;btn 1&quot;</span> <span style="color: #339933;">/&gt;</span>
    <span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span>
    <span style="color: #339933;">&lt;</span>div<span style="color: #339933;">&gt;</span>
        <span style="color: #339933;">&lt;</span>p<span style="color: #339933;">&gt;&lt;/</span>p<span style="color: #339933;">&gt;</span>
        <span style="color: #339933;">&lt;</span>input type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;button&quot;</span> value<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;btn 2&quot;</span> <span style="color: #339933;">/&gt;</span>
    <span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span>
<span style="color: #339933;">&lt;/</span>div<span style="color: #339933;">&gt;</span></pre></div></div>

<p>javascript:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> controllerExample<span style="color: #009900;">&#40;</span>node<span style="color: #339933;">,</span>idx<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">node</span> <span style="color: #339933;">=</span> node<span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">idx</span> <span style="color: #339933;">=</span> idx<span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">clickCount</span> <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">setEventHandlers</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
controllerExample.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">setEventHandlers</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
      $<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">node</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">find</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'input'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'click'</span><span style="color: #339933;">,</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">handleClick</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
controllerExample.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">handleClick</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">clickCount</span><span style="color: #339933;">++;</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">node</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">find</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'p'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">text</span><span style="color: #009900;">&#40;</span>
        <span style="color: #3366CC;">'Button is clicked '</span><span style="color: #339933;">+</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">clickCount</span><span style="color: #339933;">+</span><span style="color: #3366CC;">' time(s)'</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h3>&#8216;this&#8217; is wrong</h3>
<p>Now that doesn&#8217;t work&#8230; When the click event fires the handleClick() function is executed but the scope is not the controllerExample instance. On execution the &#8216;this&#8217; keyword points to the input element. So we see &#8216;Button is clicked NaN time(s)&#8217;.</p>
<p>The Prototype javascript library has a solution for this by extending the basic function object type with the bind() and bindAsEventListener() methods. Very nice but to include Prototype just for that&#8230; bad idea. It&#8217;s perfectly possible to separately implement a similar bind() function method but that still creates an additional (besides jQuery) dependency for that method. Let&#8217;s keep the mess to a minimum and keep it &#8216;in&#8217; the controllerExample object.</p>
<h3>Closure</h3>
<p>Prototype&#8217;s bind() function uses what is called a closure: A function defined within a function. The benefit is that the inner function, which in the following example is returned by the outer function, has access to the outer functions local variables <em>after</em> the outer function has returned.</p>
<p>Properly &#8216;binding&#8217; the handleClick event handler now looks like this:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">controllerExample.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">setEventHandlers</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> _scope <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> getHandleClick <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// window</span>
        console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span>_scope<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// controllerExample</span>
        <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066; font-weight: bold;">return</span> _scope.<span style="color: #660066;">handleClick</span>.<span style="color: #660066;">call</span><span style="color: #009900;">&#40;</span>_scope<span style="color: #339933;">,</span>event<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">node</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">find</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'input'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'click'</span><span style="color: #339933;">,</span>getHandleClick<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>getHandleClick() returns a function that, when executing, still has access to _scope which <em>is</em> the correct scope. The console.log lines are there to illustrate that inside the inner function we can&#8217;t use &#8216;this&#8217;. The getHandleClick() function has no object scope so it&#8217;s &#8216;this&#8217; is the window scope. But the object scope can be passed into by copying &#8216;this&#8217; to a new variable _scope and use that inside the closure.</p>
<p>More information about closures: <a href="http://www.javascriptkit.com/javatutors/closures.shtml">Javascript closures 101</a> (basic) and <a href="http://www.jibbering.com/faq/faq_notes/closures.html">This article on jibbering.com</a> (advanced).</p>
<h3>routeEvent</h3>
<p>Now the above is fine if there&#8217;s just one or two event handlers to be added but is not really &#8216;generic&#8217;. So let&#8217;s create a more generic &#8216;routeEvent&#8217; method that creates a closure for the eventHandler that is passed in:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">controllerExample.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">setEventHandlers</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">node</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">find</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'input'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span>
        <span style="color: #3366CC;">'click'</span><span style="color: #339933;">,</span>
        <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">routeEvent</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">handleClick</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #006600; font-style: italic;">// ...</span>
controllerExample.<span style="color: #660066;">prototype</span>.<span style="color: #660066;">routeEvent</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>eventHandler<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> _scope <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">return</span> eventHandler.<span style="color: #660066;">call</span><span style="color: #009900;">&#40;</span>_scope<span style="color: #339933;">,</span>event<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Now the handleClick() method will be called with the correct &#8216;this&#8217; and is also provided with the jQuery event object.</p>
<p>A demo putting it al together can be seen <a href="/static/event_scope_closure/">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tibobeijen.nl/blog/2009/07/27/taming-the-javascript-event-scope-closures/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

