68

I'm interested what's the reason to have call() method in JS. It seems it duplicates usual method of calling this.

For example, I have a code with call().

var obj = {
    objType: "Dog"
}

f = function(did_what, what) {
    alert(this.objType + " " + did_what + " " + what);
}

f.call(obj, "ate", "food");

The output is "Dog ate food". But the same result I can get assigning the function to the object.

var obj = {
    objType: "Dog"
}

f = function(did_what, what) {
    alert(this.objType + " " + did_what + " " + what);
}

obj.a = f;
obj.a("ate", "food");

The result is the same. But this way is more understandable and convenient to use. Why call() is needed?

Green
  • 28,742
  • 61
  • 158
  • 247
  • 3
    Well, you won't be able to assign the function to an object in all cases. E.g. if you create a function which accepts a callback and you allow also the context to be passed, you *could* assign the callback to the object and call it directly, but which name would you choose? You might override an existing method. `call` provides a simple way to solve that issue. – Felix Kling Jan 25 '12 at 11:24

5 Answers5

70

call is used when you want to control the scope that will be used in the function called. You might want the this keyword to be something else than the scope you assigned the function to, in those cases you can use call or apply to call the function with your own scope.

F.ex, it also allows you to call utility methods outside the scope, like when using "private" functions:

var obj = (function() {
    var privateFn = function() {
        alert(this.id);
    }
    return {
        id: 123,
        publicFn: function() {
            privateFn.call(this);
        }
    };
}());

obj.publicFn();

In the example above, privateFn is not exposed in obj but it can still be constructed as if it was a part of the public scope (using this in the same way).

David Hellsing
  • 106,495
  • 44
  • 176
  • 212
  • 3
    But controlling the scope is what bind is for so instead you can do privateFn.bind(this)(); so is call ever necessary or does it just look better? – Curtis Feb 23 '16 at 22:10
  • 1
    @Curtis In this example you have no choice, try substituting the line `publicFn: function() { ... }` with `publicFn: privateFn.bind(this)`. While you're defining the function, the object you return hasn't been created yet so the context will simply be `window`, as there's no other context at that moment. – Alexander Derck May 16 '17 at 11:24
  • publicFn: function() { privateFn.bind(this)(); } Well you can do this so call doesn't need to exist in javascript since you normally call functions with parenthesis, and call is never necessary. – Curtis May 25 '17 at 20:05
  • 1
    @Curtis `bind` creates a new copy of the function while `call` does not. Also, `fn.bind(this)('foo')` is a less readable version of `fn.call(this, 'foo')` – David Hellsing Oct 11 '17 at 12:18
48

2017 Update

All functions by way of Function.prototype have the .call method. The reason to use .call() is to specify what the variable "this" refers to.

MDN specifies:

The call() method calls a function with a given this value and arguments provided individually.

Consider the following:

function x() {
    return this;
}

x()

In strict mode x() returns undefined in non strict mode it returns the Global object, Window in a browser context.

Example with .call() we tell it what "this" refers to:

function x() {
    return this;
}

var obj = {
    myName      : 'Robert',
    myLocation  : 'Earth'
}

x.call(obj);

Result: {myName: "Robert", myLocation: "Earth"}. In the above example we are specifying the obj object as the value of this inside the function x()

It can be used to emulate inheritance in OOP.

Example:

var Robert = {
    name: "Robert Rocha",
    age: 12,
    height: "5,1",
    sex: "male",
    describe: function() {
        return "This is me " + this.name + " " + this.age + " " + this.height + " " + this.sex;
    }
};

Lets say that the above is a master object(prototype) and you want to inherit the function describe in another object:

var Richard = {
    name: "Richard Sash",
    age: 25,
    height: "6,4",
    sex: "male",
}

The Richard object does not have the describe function and you want to simply inherit ,so to speak, the function. You would do it like so:

console.log( Robert.describe.call( Richard ) );

Output: This is me Richard Sash 25 6,4 male

Robert
  • 10,126
  • 19
  • 78
  • 130
  • 1
    Thanks. ur answer is very easy to understand. – htoniv Mar 17 '16 at 07:17
  • This answer doesn't explain if there's `this` parameter in the `call` method like: `Robert.describe.call(this,Richard)` . What's the role of `this` here? – TomSawyer Aug 17 '16 at 19:36
  • @TomSawyer in this example `this` refers to the current object, the calling object. With `.call()` you can write a method once and inherit it in another object of your choosing without having to write it again, taking care of the DRY principle. – Robert Aug 18 '16 at 00:59
  • Wouldn't it make more sense to have a `Person` object with a prototype function `describe` and then Robert/Richard can be based on this object (i.e. `var Robert = new Person(...);`)... I guess you mentioned above that Robert is a master object, so I guess we would use `.call` in places where we need to use a function from another object for another object? – benscabbia Feb 28 '17 at 06:55
  • Great explain! Thanks! – Caius Jan 28 '18 at 11:58
7

You would probably use the second way in your example, but sometimes you want to use one object's functions on another object. An example would be using Array methods on Array-like objects like NodeLists

var el = document.getElementById("foo");
[].forEach.call(el.children, function(child, index) {
    //Iterate over an element's children, performing an action on each one
});
Dennis
  • 32,200
  • 11
  • 64
  • 79
5

It's to do with the concept of a first class function. Basically languages like Javascript allow you to treat functions as things their own right. Functions can be stored in variables or passed to other functions.

call() provides a way to execute a free standing function not attached to any other object.

Rob Agar
  • 12,337
  • 5
  • 48
  • 63
  • 4
    Can you provide an example of that please? ("a way to execute a free standing function"). Can we not call the function without `call()`? – Nelu Dec 09 '13 at 22:18
1

After I read this , I understand why.

A common mistake for new JavaScript programmers is to extract a method from an object, then to later call that function and expect it to use the original object as its this (e.g., by using the method in callback-based code).

Without special care, however, the original object is usually lost. Creating a bound function from the function, using the original object, neatly solves this problem:

this.x = 9;    // 'this' refers to global 'window' object here in a browser
const module = {
  x: 81,
  getX: function() { return this.x; }
};

module.getX();
//  returns 81

const retrieveX = module.getX;
retrieveX();
//  returns 9; the function gets invoked at the global scope

//  Create a new function with 'this' bound to module
//  New programmers might confuse the
//  global variable 'x' with module's property 'x'
const boundGetX = retrieveX.bind(module);
boundGetX();
//  returns 81

The origin is here

tdy
  • 36,675
  • 19
  • 86
  • 83
liukuo362573
  • 39
  • 10