7

I've come across some code that has this sort of pattern in numerous places:

this.someFunction.call(this, param);

but it seems to me just a more verbose way of typing

this.someFunction(param)

The pattern sometimes appears inside a function which is provided as a callback. It happens to use Backbone, in case that's relevant. Something like this:

Backbone.View.extend({
    // other stuff ...

    someFunction: function(param) {
        // ...
    },
    anotherFunction: function() {
        this.collection.on("some_event", function() {
            this.someFunction.call(this, param);
        });
    }
});

Does the pattern actually have an effect that isn't the equivalent of this.someFunction(param) or was someone just nervous about the closure not capturing the correct this?

Thanks for any insights!

Jeffrey Martinez
  • 4,384
  • 2
  • 31
  • 36
  • 3
    *"or was someone just nervous about the closure not capturing the correct `this`"* `this` is a special value inside functions and is not affected by scope. (exception: ES6 arrow functions). I don't see a reason here to prefer `.call` over a normal function call. – Felix Kling Mar 18 '15 at 22:38
  • Both are equivalent probably some kind of coding convention. Scripts are also obfuscated pretty often. – kidwon Mar 18 '15 at 22:42
  • note that using call() adds some overhead and slows down execution, which is especially apparent in loops. the code could actually be written as `this.collection.on("some_event", this.someFunction.bind(this, param));`which locks _this_ ahead of time, which can be faster than call(). although, depending on how backbone uses _this_, you might need to duplicate the bound value in anotherFunction() to have the right _this_ at that time. – dandavis Mar 18 '15 at 22:52
  • Are you sure that `call` is being used in the real code rather than `apply`? If `param` was an array (or array-like object such as `arguments`) and `apply` was being used then it would make sense. – mu is too short Mar 18 '15 at 23:01
  • @muistooshort yep, I'm sure it's `call`, I had a feeling someone would ask that though :) – Jeffrey Martinez Mar 18 '15 at 23:05
  • `param` in some cases is actually just a string, `this.someFunction.call(this, "a string");` – Jeffrey Martinez Mar 18 '15 at 23:23

2 Answers2

2

Does the pattern actually have an effect that isn't the equivalent of this.someFunction(param)?

No, they are indeed the same. Assuming that this.someFunction is a function that inherits .call from Function.prototype (but that's nit-picking).

Looks like someone was overcautious, or the code is a remains of something that did not use this twice. Or maybe the author was aware of the this-context-in-callbacks issue but failed to handle it correctly.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
1

I don't see any reasons to use such way of function call in code you provided. Here is better to use direct function call like this (if you need no modification with arguments)

this.collection.on("some_event", this.someFunction, this); 

or

this.collection.on("some_event", function() {
    this.someFunction(//some modified args)
}, this); 

And let me provide the example of proper usage of .call. Sure u've seen this:

Array.prototype.slice.call(arguments, 2); 

As arguments is not an array, we can 'borrow' Array method to operate with arguments. If you will try to call slice on arguments you will get an error

Evgeniy
  • 2,915
  • 3
  • 21
  • 35