Wow, it’s been almost seven months since I posted anything here. But now I’m going to try to get this blog kick-started. Here at Applied Predictive Technologies (APT), we’ve been spending some time lately thinking through which JavaScript libraries we should be using since our current library, YUI 2, is about to be retired in favor of YUI 3. It would seem that YUI 3 would be the obvious choice, but since it isn’t backwards compatible and the syntax is quite different, the cost of switching to that versus jQuery or another library. I personally have a particular affection for jQuery because I wrote an internal dashboard for helping our engineers manage their production features and bugs with it. When they say it’s the “write less, do more” library, they’re not kidding.
Anyways, the point of all of this is that I’ve been trying to weigh some of the pros and cons of the different libraries as we begin to think about where we should begin to migrate our code going forward. I’ll devote another post to enumerating some of the differences I’ve found between those two libraries, but suffice it to say, I’ve seen awesome sites written with both, so I’m not too concerned that our choice is going to have a big impact on our ability to create a great client side experience. After playing with YUI 3 for a while over the past few days, especially their Widget framework, it seems like a natural progression of where we were headed with our code base anyways, so YUI 3, here we come.
Even though I’ve made a decision to pursue YUI 3, there is still a ton I don’t know about it. The components and utilities it offers are very different from YUI 2, although you can start to see some convergence in later point releases of YUI 2. I’m sure there are others in the same boat, so I’m going to begin blogging about YUI 3: the new functionality, the new frameworks, and how to “translate” YUI 2 to YUI 3. At the same time, I hope to walk through, line by line, some of the YUI functionality to help folks get a better understanding of how the Yahoo! engineers structure their code.
Y.bind
This may not be the most interesting topic for starters, but it’s one that illustrates a cool technique in JavaScript that John Resig has blogged about before called partial. The official documentation for this method is here. You can probably guess from the name, but this method has something to do with binding functions to objects. It’s most common use case is with event handlers. In YUI 2, you might have the following code:
YAHOO.util.Event.on("myElement", "click", this.myClickHandler, this, true);
This just says, when a user clicks on the element with ID “myElement”, call the method “myClickHandler,” which is a method of some object and execute that function in the context of that object. This is a pretty common setup. Here’s how you’d do the same thing in YUI 3:
Y.get("#myElement").on("click", Y.bind(this.myClickHandler, this));
This looks pretty similar. Most of this is relatively straightforward and reminds me a lot of another JavaScript library (cough…jQuery…cough), but the one piece I was interested in was the “Y.bind” method. Here’s what the method looks like as of the YUI 3 Beta 1:
/**
* Returns a function that will execute the supplied function in the
* supplied object's context, optionally adding any additional
* supplied parameters to the beginning of the arguments collection the
* supplied to the function.
*
* @method bind
* @param f {Function|String} the function to bind, or a function name
* to execute on the context object
* @param c the execution context
* @param args* 0..n arguments to include before the arguments the
* function is executed with.
* @return {function} the wrapped function
*/
Y.bind = function(f, c) {
var xargs = arguments.length > 2 ? Y.Array(arguments, 2, true) : null;
return function () {
var fn = L.isString(f) ? c[f] : f,
args = (xargs) ? xargs.concat(Y.Array(arguments, 0, true)) : arguments;
return fn.apply(c || fn, args);
};
};
This method is pretty short, but what is it doing? Let’s break it down line by line. Notice that it takes two required arguments — a function and an “execution context,” which is a fancy way of saying an object that will be the “scope” of the function when we call it — followed by any number of optional arguments that will be included as arguments to the eventual function call. The first line of this method determines whether we have more than two arguments, and if so, parses out all of the extra arguments into an array.
After that, we create a function object we’re going to return. This is one of the things I love about JavaScript. You can have a function that returns another function. Really powerful. In this case, the function we are returning first checks to see if the argument “f” is a string, and if so, assumes it’s a method on the context object. This is just for convenience. I could’ve re-written my example as:
Y.get("#myElement").on("click", Y.bind("myClickHandler", this));
and it would’ve worked exactly the same way. Now that we have the function, we want to determine what arguments to pass to it. If we passed extra arguments to the Y.bind call, then we want to concatenate the arguments that will be passed to this returned function onto those arguments. Otherwise, just use whatever arguments will be passed to this function. Finally, this function will call our original method with the context we passed in (or if it wasn’t passed in, in the context of the function we passed in itself…not quite sure what the use case for that is), applying the set of arguments we’ve merged together. And that’s it.
Before finishing this, it might be helpful to see an example of how what adding extra arguments does:
var alertAllTheArguments = function() {
for (var i = 0, len = arguments.length; i < len; i++) {
alert(arguments[i]);
}
};
var alertOneAndTwoFirst = Y.bind(myFunc, null, 1, 2));
alertOneAndTwoFirst(); // alert(1); alert(2);
alertOneAndTwoFirst("hello", "world"); // alert(1); alert(2); alert("hello"); alert("world");
So as you can see, it’s basically a way to enforcing that certain arguments are always populated with certain values. You might think, this is great, but what if I want the arguments I’m passing to be at the end of the arguments list instead of at the beginning? Well, luckily, there’s a method for that too: Y.rbind. If you want to do more complex things, see John Resig’s article above which has more on this technique.
Social Links