Recently, Knockout’s original author Steve Sanderson released a plugin called knockout-projections which optimises the performance of the observable array methods filter and map. In this post, I’ll take a peek into the future by combining this plugin with the forthcoming ES6 arrow functions to produce some very terse and highly efficient collection bindings.
Array filter and map
Before I jump into arrow functions I’ll quickly introduce a couple of the ES5 array methods, you can safely skip this section if you’re familiar with them. However, if you’re not already using these methods, you’re missing out. Equivalent to the C# IEnumerable methods
select, they’re basically shorthand for -
They’ve now got widespread adoption in the browsers and are easily poly-filled. Consider yourself informed.
If you haven’t already heard, ES6 will introduce a new syntax for lambdas called arrow functions. Now the new syntax might only shave off a few characters (21 if you’re feeling pedantic), but to me it looks so much neater -
Unfortunately, browser support for ES6 just isn’t there yet and short of inventing a time machine there’s not much we can do about that… or is there?
A solution (of sorts)
In Knockout 3.0 it is now very easy to hook into this preprocessing. For example we can add a preprocessor to all binding values with something like -
That means that all we need to do is use an ES6 compatible parser to parse the
Esprima, estraverse and escodegen are existing tools for static meta-programming, a fancy way of saying “messing around with the source code before it’s executed”. The tools are well documented on their respective sites but and in this case I think the APIs are obvious enough -
We take the source
Rewriting an arrow function expression
To become -
This basic implementation just maps the parameters as they are, adds a return statement to the body expression and lexically binds this. I’ve also thrown in a
ko.unwrap to allow us to be lazy about referencing the observable itself or the observable’s value.
It looks complicated but actually it’s just quite a verbose, repetitive pattern of nested objects representing the nodes of the AST. The comments highlight the two places that the substitution takes place.
You can see a really basic example in action here, make sure you peek at the DOM to see the arrow function in the binding. The source is available here and creating your own example with browserify should be as simple as -
So whilst not the most practical end result i.e. you probably don’t want to be loading a full-blown ES6 parser, tree traversal and code generation logic along with your app. I do think it gives a glimpse of the future of bindings in the browser. I look forward to the day that all of this comes for free but until then I’ll happily buy a beer for the first person to turn this into a build-time grunt task.