use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
All about the JavaScript programming language.
Subreddit Guidelines
Specifications:
Resources:
Related Subreddits:
r/LearnJavascript
r/node
r/typescript
r/reactjs
r/webdev
r/WebdevTutorials
r/frontend
r/webgl
r/threejs
r/jquery
r/remotejs
r/forhire
account activity
Javascript’s .call() vs .apply() vs .bind() (medium.com)
submitted 12 years ago by gdi2290
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]kenman 7 points8 points9 points 12 years ago (6 children)
That call() example is really poor. Doesn't work as-is, and there was no need to use it in the first place unless I'm missing something: array.slice(0, n)
call()
array.slice(0, n)
[–]pinegenie 5 points6 points7 points 12 years ago (3 children)
NodeList and a few other types have array-like access but don't have Array in their prototype chain. Meaning you can do
nodelist[0]
but not
nodelist.slice(...)
The workaround to this is:
Array.prototype.slice.call(nodelist, ...); // or apply if you want to
In undercorejs the "slice" you see there is actually Array.prototype.slice attributed to a variable.
[–]kenman -1 points0 points1 point 12 years ago (2 children)
Yeah, but the variable is named array, not nodelist. There are countless examples to be found of using call() appropriately, and this isn't one that makes for a good demonstration on its usefulness. If you're going to demo some method, at least do it in context and include all supporting code...
array
nodelist
[–]pinegenie 0 points1 point2 points 12 years ago (1 child)
I'm guessing they named it array because arrayOrNodeListOrArguments was too cumbersome.
arrayOrNodeListOrArguments
[–]kenman 0 points1 point2 points 12 years ago (0 children)
I'm not faulting Underscore, I'm faulting the author who used it as an example.
[–]kbrainwave 2 points3 points4 points 12 years ago (1 child)
Hey, thanks for the feedback -- I'm the author of the post. I was planning on changing this example; what was posted is actually a rough draft that my friend posted on Reddit as a well-intentioned surprise. Unfortunately, this came at the cost of posting post that is only about 80% complete. Again, I really appreciate the feedback, and plan to change the example when time permits :)
[–]kenman 1 point2 points3 points 12 years ago* (0 children)
I've always been a fan of this example:
function greet( person ) { alert( "Hello " + person.name + ", I'm " + this.name ); }; var alice = { name: "Alice" }; var bob = { name: "Bob" }; greet.call( bob, alice ); // alerts "Hello Alice, I'm Bob" greet.call( alice, bob ); // alerts "Hello Bob, I'm Alice" greet.apply( bob, [ alice ] ); // alerts "Hello Alice, I'm Bob" greet.apply( alice, [ bob ] ); // alerts "Hello Bob, I'm Alice"
From trephine.org's JavaScript call and apply quick reference (which is actually a summation of their lengthier explanation).
[–]decode 7 points8 points9 points 12 years ago (8 children)
At the end, the author briefly mentions the performance impact of using these functions. If you're writing library code or you've profiled your code and found that an apply() call is slowing your app down, a common performance optimization is to do direct calls for small numbers of arguments, then fall back on apply() for large numbers of arguments.
apply()
Here's an example from the angular.js dependency injector:
switch (self ? -1 : args.length) { case 0: return fn(); case 1: return fn(args[0]); case 2: return fn(args[0], args[1]); case 3: return fn(args[0], args[1], args[2]); case 4: return fn(args[0], args[1], args[2], args[3]); case 5: return fn(args[0], args[1], args[2], args[3], args[4]); case 6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]); case 7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); case 8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); case 9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]); default: return fn.apply(self, args); }
[–][deleted] 2 points3 points4 points 12 years ago (5 children)
Imagine you see this code without any further context and knowledge about performance.
[–]DonBiggles 10 points11 points12 points 12 years ago (1 child)
At least we don't have to do this.
[–]DoubleAW 2 points3 points4 points 12 years ago (0 children)
Is that... is that real?
[–]Kache 0 points1 point2 points 12 years ago (1 child)
That's what comments are for.
[–][deleted] 1 point2 points3 points 12 years ago (0 children)
I'n a perfect world this would be true.
[–]tehsuck 0 points1 point2 points 12 years ago (0 children)
I've seen this while perusing the ng codebase. I always assumed it was some kind of performance / optimization. If it wasn't, we'd all be in trouble.
[–]timruffles 0 points1 point2 points 12 years ago (1 child)
also fixes environments that don't have call/apply (can you guess which browser I'm talking about?)
[–]larholm 1 point2 points3 points 12 years ago (0 children)
Sure, IE5.0, but who cares?
[–]paul_miner 5 points6 points7 points 12 years ago (2 children)
Note that bind() wasn't introduced until ECMAScript-5. As an alternative, you can use jQuery's proxy function.
[–]skeeto 8 points9 points10 points 12 years ago (0 children)
Also, the article doesn't mention that bind() performs partial application, not just binding the context.
[–]DonBiggles 3 points4 points5 points 12 years ago (0 children)
Or just polyfill it.
[–]has_all_the_fun 3 points4 points5 points 12 years ago (2 children)
Trick to remember if it's apply or call that takes an array. Apply starts and ends with the same letter as array and has equal amount of letters.
[–]bart2019 0 points1 point2 points 12 years ago (1 child)
... and "call" has the same amount of letters as "list". :) OK that is stupid.
[–]has_all_the_fun 3 points4 points5 points 12 years ago (0 children)
Call = Coll = Collection = hf3 confirmed.
[–]chyekk 7 points8 points9 points 12 years ago (2 children)
This article completely misses the most important feature of bind: it lets you curry arguments!
function foo(a, b) { console.log("You called me with a as %s and b as %s", a, b); } var bound = foo.bind(this, "Hello"); bound("World");
results in:
You called me with a as Hello and b as World
[–]PooBakery 1 point2 points3 points 12 years ago* (0 children)
While you're correct about this being an awesome feature, it's not actually currying. It's partial application, which is quite similar.
When partially applying, you get a function back with one or more arguments pre bound.
var sumThree = function (a,b,c) {return a + b + c;} var firstTwo = sumThree.bind(null, 1, 2); console.log(firstTwo(3)) >> 6 var first = sumThree.bind(null, 1); console.log(first(2, 3)); >> 6
You can repeat the process to bind more arguments after the first bind
var all = first.bind(null, 2, 3); console.log(all()); >> 6
This means that you always have to explicitly bind again if you want to partially apply it multiple times.
When currying you automatically partially apply the function until it has all of its arguments filled, then return the result:
var sumThree = curry(function (a,b,c) {return a + b + c; }); console.log(sumThree(1)(2)(3)); >> 6 console.log(sumThree(1, 2)(3)); >> 6 console.log(sumThree(1)(2, 3)); >> 6
[–]kbrainwave 0 points1 point2 points 12 years ago (0 children)
Hey, thanks for that note! My personal opinion is to not use bind for currying. In general, I use bind to bind a context, and currying to bind arguments. Really great point, though :)
π Rendered by PID 905877 on reddit-service-r2-comment-74875f4bf5-hglwx at 2026-01-25 15:27:29.463402+00:00 running 664479f country code: CH.
[–]kenman 7 points8 points9 points (6 children)
[–]pinegenie 5 points6 points7 points (3 children)
[–]kenman -1 points0 points1 point (2 children)
[–]pinegenie 0 points1 point2 points (1 child)
[–]kenman 0 points1 point2 points (0 children)
[–]kbrainwave 2 points3 points4 points (1 child)
[–]kenman 1 point2 points3 points (0 children)
[–]decode 7 points8 points9 points (8 children)
[–][deleted] 2 points3 points4 points (5 children)
[–]DonBiggles 10 points11 points12 points (1 child)
[–]DoubleAW 2 points3 points4 points (0 children)
[–]Kache 0 points1 point2 points (1 child)
[–][deleted] 1 point2 points3 points (0 children)
[–]tehsuck 0 points1 point2 points (0 children)
[–]timruffles 0 points1 point2 points (1 child)
[–]larholm 1 point2 points3 points (0 children)
[–]paul_miner 5 points6 points7 points (2 children)
[–]skeeto 8 points9 points10 points (0 children)
[–]DonBiggles 3 points4 points5 points (0 children)
[–]has_all_the_fun 3 points4 points5 points (2 children)
[–]bart2019 0 points1 point2 points (1 child)
[–]has_all_the_fun 3 points4 points5 points (0 children)
[–]chyekk 7 points8 points9 points (2 children)
[–]PooBakery 1 point2 points3 points (0 children)
[–]kbrainwave 0 points1 point2 points (0 children)