<?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>OneMarco &#187; callbacks</title>
	<atom:link href="http://onemarco.com/tag/callbacks/feed/" rel="self" type="application/rss+xml" />
	<link>http://onemarco.com</link>
	<description>Web development in the age of Web 2.0</description>
	<lastBuildDate>Fri, 18 Feb 2011 06:03:25 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>JavaScript Callbacks and Binding (and Callback Arguments and References)</title>
		<link>http://onemarco.com/2008/11/12/callbacks-and-binding-and-callback-arguments-and-references/</link>
		<comments>http://onemarco.com/2008/11/12/callbacks-and-binding-and-callback-arguments-and-references/#comments</comments>
		<pubDate>Thu, 13 Nov 2008 03:03:51 +0000</pubDate>
		<dc:creator>Marco</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[binding]]></category>
		<category><![CDATA[callbacks]]></category>

		<guid isPermaLink="false">http://onemarco.com/?p=9</guid>
		<description><![CDATA[Callback functions are used in JavaScript (JS) extensively. They are required for AJAX/XHR, event handling, and in popular JS libraries. However, passing around functions as arguments can cause headaches, especially for beginner JS programmers. Problems with binding/this One of the &#8230; <a href="http://onemarco.com/2008/11/12/callbacks-and-binding-and-callback-arguments-and-references/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>
	Callback functions are used in JavaScript (JS) extensively. They are required 
	for AJAX/XHR, event handling, and in popular JS libraries. However, passing around
	functions as arguments can cause headaches, especially for beginner JS programmers.
</p>
<h3>Problems with binding/<code>this</code></h3>
One of the biggest problems with passing functions as callbacks is <code>this</code> and what it
refers to. You usually run into the problem when passing an object&#8217;s method as a
callback function.  Another way to encounter this problem is by passing as a callback a function that
expects to be bound to a certain type of object.  You&#8217;ll usually get an error stating that
<code>this.someProperty</code> is undefined.  You can resolve this with 
<code>Function.apply</code>, <code>Function.call</code> or a closure. For example:
<code class="brush: js">//using Function.call
takesCallback(
	function callbackProxy(argOne, argTwo){
		//assume myFunction is already defined
		myFunction.call(myObject, argOne, argTwo);
	}
);

//or using Function.apply
takesCallback(
	function callbackProxy(argOne, argTwo){
		//assume myFunction is already defined
		myFunction.apply(myObject, [argOne, argTwo]);
	}
);

//or using a closure
takesCallback(
	function callbackProxy(argOne, argTwo){
		//assume myObject is already defined
		myObject.myMethod(argOne, argTwo);
	}
);</code>
<p>In the code above, the function <code>takesCallback</code> takes a callback function as its
only argument and calls that function at a later time with two arguments.  The function, <code>callbackProxy</code> is 
a wrapper function that takes the arguments and passes them to the real callback, while ensuring
that the function is bound to the correct object.</p>
<span id="more-9"></span>
<h3>Problems with Arguments</h3>
Another problem with callback functions is that the arguments
passed to the callback function are often out of your
control. Sometimes you need more information than what is
passed to your callback function by the caller. This, too can be solved with a closure. For example:
<code class="brush: js">function main(){
	var myVarOne = "one";
	takesCallback(
		function callbackProxy(argOne){
			//assume myFunction is alread defined
			myFunction(argOne, myVarOne);
		}
	);
}</code>
<p>Again, the <code>callbackProxy</code> function takes care of calling the real callback with
the correct arguments.  In this case it appends myVarOne to the list of arguments.</p>
<h3>Problems with references</h3>
<p>The issue with references does not come up often. But when it does, it can be difficult to 
solve. When you use a callback proxy to pass additional arguments to the real callback, you
may find that the values of those arguments have changed between the time the callback proxy
was created and when it was called.  This will happen if you are using a loop counter as
an argument for your callback or if you change the value of the variable for some other reason.
For example:</p>
<code class="brush: js">//looping
for(var i = 0; i &lt; 5; i++){
	takesCallback(function callbackProxy(){
		//assume myFunction is already defined
		myFunction(i);
	})
}

//general example
var x = 2;
takesCallback(function callbackProxy()){
	myFunction(x);
}
x = x * 2;</code>
<p>In both of the cases above, when <code>myFunction</code> is called, the value of the first
argument will be 4.  This is true for all iterations of the loop. It happens because the references to <code>i</code> and <code>x</code>
are never broken.  In the general example, you can eliminate this problem by using another variable
in place of <code>x</code>. In the looping example, the fix is more complicated:</p>
<code class="brush: js">for(var i = 0; i &lt; 5; i++){
	takesCallback(
		(function breakReference(arg){
			return function callbackProxy(){
				myFunction(arg);
			};
		})(i)
	);
}</code>
<p>This code creates the callback proxy with the <code>breakReference</code> function.  The
<code>breakReference</code> function is executed immediately and returns the callback proxy.
The reference to <code>i</code> is broken because <code>i</code> is passed as an argument.
In JS, primitives passed as arguments are passed by value and objects passed as arguments are passed by reference.
So, if you are trying to break a reference to an object, this method will not work.</p>
<h3>A better solution</h3>
<p>You probably don&#8217;t want to remember all these tricks or write these routines over and over. Personally, I dislike
closures because they can become nested several levels deep, making debugging and reading your code difficult.  If you&#8217;ve ever written a web application,
you know the code can quickly become a mess.  Closures can compound that mess, so I try to stay away from them or hide them in other
functions.  So what can you do? You can write a function to take care of these issues for you and use it as often as you need or you can use
a binding function from your favorite JS library. Or, you can use the one I already wrote (if you don&#8217;t use a library and don&#8217;t want
to write your own).</p>
<code class="brush: js">/**
 * @param {Function} func the callback function
 * @param {Object} opts an object literal with the following
 * properties (all optional):
 * scope: the object to bind the function to (what the "this" keyword will refer to)
 * args: an array of arguments to pass to the function when it is called, these will be
 * appended after any arguments passed by the caller
 * suppressArgs: boolean, whether to supress the arguments passed
 * by the caller.  This default is false.
 */
function callback(func,opts){	
	var cb = function(){
		var args = opts.args ? opts.args : [];
		var scope = opts.scope ? opts.scope : this;
		var fargs = opts.supressArgs === true ?
			[] : toArray(arguments);
		func.apply(scope,fargs.concat(args));
	}
	return cb;
}

/* A utility function for callback() */
function toArray(arrayLike){
	var arr = [];
	for(var i = 0; i &lt; arrayLike.length; i++){
		arr.push(arrayLike[i]);
	}
	return arr;
}</code>
<p>The <code>callback</code> function is fairly straight forward. It takes a function and
and an object literal and returns a callback function that takes care of the 
problems discussed earlier.  The properties of the object literal are all optional and will
default to what is normal behavior for callbacks. The object literal defines the scope and extra arguments.  It can
also supress the arguments provided by the caller (the extra arguments are still used). This is useful when you don&#8217;t need the
arguments provided by the caller or when you are using a function that isn&#8217;t always called as a callback. Here is 
an example of how to use it.</p>
<code class="brush: js">takesCallback(callback(myFunction,{scope:myObject,args:[myArgOne,myArgTwo],suppressArgs:true}));

//or
takesCallback(myObject.myMethod,{scope:myObject,args:[myArgOne]});</code>
<p>As you can see, using the <code>callback</code> function is much easier than using the tricks shown above.
If you are using callbacks often, as is the case with event handling and AJAX, this is very handy tool.  You can
create your objects, methods, and functions once and quite easily reuse them.</p>]]></content:encoded>
			<wfw:commentRss>http://onemarco.com/2008/11/12/callbacks-and-binding-and-callback-arguments-and-references/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

