Sometimes we know values for some arguments to a function. JavaScript allows applying or binding these values to the function. The result is a new function that wraps around old function supplying all arguments
1 | function add(a, b) { return a + b; } |
The Function.prototype.bind
method is included in EcmaScript5 standard and is
supported in almost every browser (Phantomjs v1 being notable exception).
You can even bind all arguments the function expects
1 | var add10to3 = add.bind(null, 10, 3); |
bind
applies arguments from left to right. What if you would like to apply
arguments from right to left? It is easy to write a function that does this, or
use a 3rd party library. For example using partialRight
from lodash is one candidate
1 | var _ = require('lodash'); |
Selective application
As a rule of thumb, I advise placing arguments least like to change on the left of the function signature.
In some cases though neither left nor right application works. For example, _.map
method takes 3 arguments: collection, callback and this
argument. Usually, the callback function can
be constructed right away, but binding it to the second argument is impossible. You cannot skip arguments!
1 | // does not work yet |
I call this problem selective application because I select which arguments to apply. Here is how this problem is solved by lodash, ramda and finally my little utility function called heroin.
lodash
Next major release of lodash v3 is going to have placeholders.
You can skip binding arguments by passing _
itself as a special value
1 | // left to right, but skip first argument |
I am looking forward to this release.
spots
To avoid waiting for lodash placeholders, I wrote my own placeholder utility spots.
1 | function add4(a, b, c, d) { return a + b + c + d; } |
Because spots
preserves the bound context (version >= 0.5.0), you can use it with methods, for example to remove
boilerplate when building middleware routes
1 | // same callbacks to check if the user is logged in and authorized |
ramda
Selective application in Ramda is a difficult question because almost every function in the library is curried by default. This makes left to right application natural, but some functions are more naturally applied from the right first. These functions are called operators. For example, the division function is an operator. Normally, it divides first argument by the second one:
var R = require('ramda');
// R.divide = function(a, b) { return a / b}
console.log(R.divide(10, 2)); // 5 (a = 10, b = 2)
If we apply a single argument to R.divide
, should it bind to the first position or the second?
After a long discussion, the Ramda authors have
decided that the application order should follow from most common use case. In this case we
often divide BY a certain number (second argument), and less often divide a certain number (first argument).
var divideBy10 = R.divide(10);
console.log(divideBy10(500)); // 50 (a = 500, b = 10)
What if you really want to apply first argument? You need to pass undefined
as the second!
var divide10 = R.divide(10, undefined);
console.log(divide10(5)); // 2 (a = 10, b = 5)
The same logic applies to any operator function where order of arguments matters (subtraction, comparisons).
The downside is that sometimes undefined
is a valid value to be applied. I would prefer using
library reference ramda
itself as a placeholder.
heroin
Finally, I have a tiny dependency injection utility called heroin. It applies arguments by name, and not by position or semantics.
1 | var selective = require('heroin'); |
Having to explicitly name arguments to apply leads to cleaner code in my opinion. On the other hand, heroin has a limitation. Successful selection depends on the original argument names, which are usually mangled during minification. I could add support for name annotations, similar to the dependency injection in AngularJs, so if this is needed, let me know via new issue.