Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

clarification on the purpose of `Function.call.apply` #143

Closed
twobitfool opened this Issue Aug 27, 2012 · 4 comments

Comments

Projects
None yet
3 participants

In the function arguments section, there is a mention of using call and apply together...

Another trick is to use both call and apply together to create fast, unbound wrappers.

function Foo() {}

Foo.prototype.method = function(a, b, c) {
    console.log(this, a, b, c);
};

// Create an unbound version of "method" 
// It takes the parameters: this, arg1, arg2...argN
Foo.method = function() {

    // Result: Foo.prototype.method.call(this, arg1, arg2... argN)
    Function.call.apply(Foo.prototype.method, arguments);
};

However, it is unclear what Function.call.apply is doing. It might be worth showing the longer equivalent, which I believe is ...

Foo.method = function() {
  var args = Array.prototype.slice.apply(arguments)
  var obj = args.shift()
  Foo.prototype.method.apply(obj, args)
};
Collaborator

timruffles commented Oct 9, 2013

Yeah I'm not sure about this one either, will research and update the text. If it's a performance thing, it needs a better explanation!

Contributor

jozsefDevs commented Jan 1, 2014

Okay, so here is an explanation of the mentioned problem:

Actually, we want to call a function within a context, with an array-like arguments object.

Function.call is a handy tool to call a function within a context, but it can't handle array-like objects as it arguments.
(The Function.call part is like Array.prototype.slice, we'd like to call a function that won't be overdefined by anyone)

So we want to call Function.call.apply what would do the job. Call "Function.call" within a context as it first argument, with an array-like object as it second.

So to fully understand this line:

Function.call.apply(Foo.prototype.method, arguments);

You would better put parenthesis while you read like:

(Function.call).apply(Foo.prototype.method, arguments);

It has nothing to do with performance I think. The Function.call part will return a function that you can call with apply. That's all.

Thanks for the followup. Makes sense.

On the first read, I was a little confused by the "trick" of calling apply on Function.call, and wondered if it would be better to be more explicit (and verbose). But I see the value in the one-liner, and (with the comments) it's a nice trick.

BTW, Happy New Year!

Contributor

jozsefDevs commented Jan 1, 2014

Happy New Year as well!

@timruffles timruffles closed this Apr 30, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment