Explicit binding
2. Explicit binding
function foo() {
console.log(this.bar)
}
var bar = "bar1";
var obj = { bar: "bar2" };
foo(); // "bar1"
foo.call(obj) // "bar2"
.call
or .apply
take the this
binding as the first parameter.Talks about that many people complain that the this
binding gets lost when the code gets complex and often falls through to the global object.But sometimes we want
this
to be very predictable. For example with Ajax calls (callbacks) the this
falls back to the global object. Or click handlers on a button for example. The solution is hard-binding. It's possible to hard-bind the
this
to a function so it always points to the same object. How to create a hard binding:
function foo() {
console.log(this.bar);
}
var bar = "bar1";
var obj = { bar: "bar2" };
var orig = foo;
foo = function() { orig.call(obj); };
foo(); // "bar"
foo.call(obj) // ???
We have overwritten foo
on line #9 so that it will always call the original foo
function with the obj
bound as this
, through the orig
pointer.So now, no matter how
Let's create a foo
is called (click handler, ajax, etc.) it's always bound to the same object.
bind utility.
function bind (fn,o) {
return function () {
fn.call(o);
};
}
function foo() {
console.log(this.bar);
}
var bar = "bar1";
var obj = { bar: "bar" };
var obj2 = { bar: "bar2" };
foo = bind(foo,obj);
foo(); // "bar"
foo.call(obj2) // still "bar"
With this "trick", the call site is now at line #2. Even when we call it as line #18. Now we can put the bind
on the function prototype
.:
if(!Function.prototype.bind2) {
Function.prototype.bind2 =
function (o) {
var fn = this; // the function!
return function () {
return fn.apply(o,arguments);
};
};
}
function foo(baz) {
console.log(this.bar + " " + baz);
}
var obj = { bar: "bar" };
foo = foo.bind2(obj);
foo("baz"); // "bar baz"
This is solution is more powerful (returns values, passes arguments
etc.)Line #16: implicit calling rule applies, so on line#4
As of ES5 this
will be the foo
function. bind
is built-in the language. Shows the polyfill on MDN. It's similar to
bind2
. The MDN polyfill is more adherent to the specs.