-
-
Save getify/9043478 to your computer and use it in GitHub Desktop.
// Modified based on: https://gist.github.com/getify/9043478/#comment-1210362 from @ZIJ | |
if (!Function.prototype.softBind) { | |
Function.prototype.softBind = function(obj) { | |
var fn = this; | |
// capture any curried parameters | |
var curried = [].slice.call( arguments, 1 ); | |
var bound = function() { | |
return fn.apply( | |
(!this || this === (window || global)) ? obj : this, | |
curried.concat.apply( curried, arguments ) | |
); | |
}; | |
bound.prototype = Object.create( fn.prototype ); | |
return bound; | |
}; | |
} | |
function foo() { | |
console.log("name: " + this.name); | |
} | |
var obj = { name: "obj" }, | |
obj2 = { name: "obj2" }, | |
obj3 = { name: "obj3" }; | |
var fooOBJ = foo.softBind(obj); | |
fooOBJ(); // name: obj | |
obj2.foo = foo.softBind(obj); | |
obj2.foo(); // name: obj2 <---- look!!! | |
fooOBJ.call(obj3); // name: obj3 <---- look! | |
setTimeout(obj2.foo,10); // name: obj <---- falls back to soft-binding |
@ZIJ Nice, thanks!
@ZIJ Why would you even need to extract the params while you are concatenating it back in the code?
var args = Array.prototype.slice.call(arguments, 1);
And then
var allArgs = args.concat(Array.prototype.slice.call(arguments));
@basherr : Because these are different "arguments". The first "arguments" (in the line with "var args = ...") are the arguments you give when calling the softBind method:
var fooOBJ = foo.softBind(obj);
The first "arguments" would here be [ obj ]. If you called...
var fooOBJ = foo.softBind(obj,1,2,3);
...the first "arguments" would be [ obj, 1, 2, 3]. If you do a slice( ..., 1) you get [1,2,3].
The second "arguments" (in the line with "var allArgs = ...") are the arguments given to the soft-bound function when it's actually called. This is what this concat is for: You can give some arguments to the softBind call to "fix" those - all calls to the soft-bound function will use these fixed arguments first - all arguments given to the soft-bound function would come after that. This is called "currying".
Example: If you did...
var fooOBJ = foo.softBind(obj, 1, 2, 3); // first "arguments" = obj, 1, 2, 3
fooObj(4,5); // second "arguments" = 4,5
then this would call foo on obj with the parameters 1,2,3,4,5, because the first "arguments" (except the first element) are added in front of the second "arguments" for the actual call.
@FlorianSchaetz Thank you very much for the detailed explanation and especially for the term Currying. I've been working with Javascript and quite learned a lot but yet this was totally new topic to me. Thanks once again
This is called "currying".
Actually, it's more appropriately called "partial application" (which is commonly confused/conflated with "currying"). Both partial application and currying are a way to preset argument(s) to a function, but they go about it differently (different usage mechanics). This usage more closely fits partial application.
Thanks for clearing that up. I got that from the "You don't know JS" book (the old one, here), where those arguments (the first ones) are called "curried".
Oops. I wrote that book 6 years ago, and I've since learned better what to call them. FTR, that mention of "currying" refers to an earlier section, where I say:
technically called "partial application", which is a subset of "currying"
THAT is also a bit of a mis-statement... one is not the subset of the other... they're more like cousins: related, but different.
JS is full of little, hard to understand, very confusing details. That's what I like about it. Ups, no, that's what I totally hate about it. ;-)
Anyway, looking forward for edition 2 of your book, unfortunately the corresponding part does not seem to be there yet, so I have (for now) to rely on edition 1, which is still more in-depth than anything else I found so far.
@getify I would like to request one thing for the 2nd Edition book to keep the words as much simple as you can. This will help non-native speakers to understand at a much faster pace. However, I am really grateful to you for this work. Stay blessed
Cool! Here's a slightly improved version: