I\'m calling some database functions from my request handlers. All of these functions do separate "error callbacks" for handling errors. Example:
fu
Binding is simple!
db.startDatabaseConnection(function(){
// whatever
}, onError.bind(this, var1, var2));
You can learn more about binding by clicking this awesome link, even though the link is sort of long.
Here's a real basic demo
// a function
var something = function (a, b, c) {
console.log(a, b, c);
};
// a binding of something with 3 defined args
var b = something.bind(null, 1, 2, 3);
// call b
b();
//=> 1 2 3
Behind the scenes, this is basically what's happening
// ES6
const myBind = (f, context, ...x) =>
(...y) => f.call(context, ...x, ...y);
// ES5
var myBind = function(fn, context) {
var x = Array.prototype.slice.call(arguments, 2);
return function() {
var y = Array.prototype.slice.call(arguments, 0);
return fn.apply(context, x.concat(y));
};
};
var b = myBind(console.log, console, 1, 2, 3);
b();
// => 1 2 3
b(4,5,6)
// => 1 2 3 4 5 6
Context?
Context allows you to dynamically change the this
of your function. Note you can only bind the context of functions defined with the function
keyword; arrow functions have a lexical this
that cannot be manipulated. This is shown for sake of completeness, but I do advise against this kind of program. It's usually better to just use another function parameter instead of relying on dynamic function context, this
. Supporting context switching like this is to enable object-oriented style in JavaScript. Unless you are using this style, I see no reason to pay attention to context.
const getCanvas = (id) =>
document.getElementById(id).getContext('2d')
const draw = function (canvas, x = 0, y = 0)
{ canvas.beginPath()
canvas.strokeStyle = this.color // `this` refers to context!
canvas.rect(x, y, this.width, this.height) // `this` refers to context!
canvas.stroke()
}
// create two contexts
const contextA =
{ color: 'blue', width: 10, height: 10 }
const contextB =
{ color: 'green', width: 10, height: 20 }
// bind the draw function to each context and the canvas
const drawA =
draw.bind(contextA, getCanvas('main'))
const drawB =
draw.bind(contextB, getCanvas('main'))
// call the bound drawing functions normally
// draw three blue squares
drawA(0, 0)
drawA(20, 0)
drawA(40, 0)
// and one green rect
drawB(80, 0)
<canvas id="main"></canvas>
Partial application
Similar to bind
ing is Partial Application
In computer science, partial application (or partial function application) refers to the process of fixing a number of arguments to a function, producing another function of smaller arity.
Here we could make a very simple partial
helper procedure which helps us accomplish this
const identity = x =>
x
const partial = (f = identity, ...x) =>
(...y) => f (...x, ...y)
const foo = (...all) =>
console.log ('array of', all)
partial (foo, 1, 2, 3) (4, 5, 6)
// 'array of', [ 1, 2, 3, 4, 5, 6 ]
Currying
Currying is related to, but not the same as, binding or partial application
In mathematics and computer science, currying is the technique of translating the evaluation of a function that takes multiple arguments (or a tuple of arguments) into evaluating a sequence of functions, each with a single argument.
const identity = x =>
x
const curry = (f = identity, arity = f.length) => x =>
{
const next = (xs = []) =>
xs.length >= arity
? f (...xs)
: x => next ([ ...xs, x ])
return next ([ x ])
}
const foo = (a, b, c) =>
console.log ('a', a, 'b', b, 'c', c)
curry (foo) (1) (2) (3)
// 'a' 1 'b' 2 'c' 3
curry (foo) ('choo') ('bye') ()
// 'a' 'choo' 'b' 'bye' 'c' undefined