最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

What's the purpose of using Function.call.apply in JavaScript? - Stack Overflow

programmeradmin8浏览0评论

I was browsing through the JavaScript Garden when I stumbled upon the Function.call.apply hack which is used to create "fast, unbound wrappers". It says:

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);
};

What I don't understand is why bother using Function.call.apply when Function.apply would suffice. After all, both of them are semantically equivalent.

I was browsing through the JavaScript Garden when I stumbled upon the Function.call.apply hack which is used to create "fast, unbound wrappers". It says:

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);
};

What I don't understand is why bother using Function.call.apply when Function.apply would suffice. After all, both of them are semantically equivalent.

Share Improve this question asked Sep 18, 2011 at 5:57 Aadit M ShahAadit M Shah 74.2k31 gold badges175 silver badges307 bronze badges 5
  • I did post a link to the JavaScript Garden. If you want to jump directly to the section which contains the post, then click here. – Aadit M Shah Commented Sep 18, 2011 at 6:10
  • tnx, - it seems that they imply this hack gives some speed up.. but, really, just do not use it. – c69 Commented Sep 18, 2011 at 6:16
  • 2 @Aadit Function.call.apply and Function.apply can't be the same here because the former applies Function.call while the second tries to apply the Function constructor. Details in my answer, but I'll bet if Ivo Wetzel came around to answer this it his would be far more eloquent and understandable. This is rather deep stuff. I agree that it's probably not something you should use unless you want colleagues to spend, oh I don't know, a half hour trying to understand it. :) – Ray Toal Commented Sep 18, 2011 at 6:53
  • 2 I think Function.call is actually a bit misleading. It should really be Function.prototype.call, since Function.callcould be overwritten. Function is just a function object after all. (Yes, this is hard to understand) – user123444555621 Commented Sep 18, 2011 at 7:21
  • 1 @Pubbaa80 Though Function.call===Function.prototype.call in the absence of nasty things, I totally agree with you. But note JSON.stringify(Object.getOwnPropertyDescriptor(Function.prototype, "call")) returns {"writable":true,"enumerable":false,"configurable":true} so the truly evil can overwrite Function.prototype.call too. Yikes. – Ray Toal Commented Sep 18, 2011 at 8:02
Add a ment  | 

2 Answers 2

Reset to default 14

No, Function.call.apply and Function.apply are not the same in this case.

Let's say the original caller invokes

Foo.method(t, x, y, z)

With call and apply together, as in the JavaScript Garden code. This executes

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

which is (loosely, writing arguments in array-notation):

Function.call.apply(Foo.prototype.method, [t, x, y, z]);

which invokes Function.call with this==Foo.prototype.method:

Foo.prototype.method.call(t, x, y, z)

which calls Foo.prototype.method with this set to t and arguments x, y, and z. Sweet. Just like in the ments. We have successfully made a wrapper.

Now suppose you left said just Function.apply instead of Function.call.apply, which you claim is semantically equivalent. You would have

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

which is (loosely)

Function.apply(Foo.prototype.method, [t, x, y, z]);

which calls the function Function (ugh!) with this set to Foo.prototype.method and arguments t, x, y, and z.

Not the same at all.

It means you can use the methods from an object on another one.

A good example is the arguments variable all functions have, it's like an array but not an array so you can call array's methods on it thus:

Array.prototype.join.call(arguments, ",");
发布评论

评论列表(0)

  1. 暂无评论