It passes the call
function to the bind
function, with the bind
function itself being the value of this
. Thus you get in return a wrapper around the bind
function that arranges for this
to be the call
function when you call it. That, in turn, is a function that lets you create a wrapper around the call
function bound to some argument you pass it.
In case you haven't been drinking coffee nonstop since you woke up this morning, step by step:
Function.bind.bind
is a reference to the bind
function. The reference is generated from a property of — confusion point 1 — the bind
function itself. Remember, the bind
function, when called with some function as the object, is used to create a wrapper around that function with this
bound to the first argument passed in.
- Thus that function call gives you a function back. That function works as if you called
Function.call.bind(something)
.
- If you pass some random function as an argument to that function, then, you get back a wrapper around the random function that, when called, will act like
randomFunction.call(whatever)
.
So:
function random() {
alert(this.foo);
}
var bb = Function.bind.bind(Function.call);
var randomcall = bb(random);
randomcall({ foo: "hello world" }); // alerts "hello world"
The ultimate point is this: you've got a function, and inside the function there's code that expects this
to have some properties, and it uses this
in one way or another. You'd really like to be able to use that function with some object here, some object there. You can obviously do that with
random.call(someObject);
But this magic "bind-bind-call" trick gives you a cheap way to create a variation on your function that lets you avoid the explicitly-coded invocation of .call()
. It also allows you to hang onto your senior front-end developer position for a little bit longer.
edit — I'm going to spoil the punch line above because I just thought of a good reason to use the bind+call trick to obtain a function that arranges to make a call to some desired function that expects to operate via this
on some "owner" object. Let's say you've got an array of strings, and you'd like to get a version of those strings in lower-case. You could write this:
var uc = ["Hello", "World"];
var lc = uc.map(function(s) { return s.toLowerCase(); });
But with the magic "bb" function we could also write:
var uc = ["Hello", "World"];
var tlc = bb(String.prototype.toLowerCase);
var lc = uc.map(tlc);
Not much of an improvement written that way, but if one were to make a set of bb()
-ified wrappers of all the handy String prototype methods, it might make more sense. Of course, everything has a price, and it's probably the case that such wrappers will have some performance impact. (If practices like this were common then runtimes could probably be improved.)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…