Search code examples
javascript

How chaining of call and bind works internally?


I've a program with functions as Person, greet, specificCall and objects as kumar and chandra.

var fullName=""
function greet() {
    console.log("Welcome "+ this.fullName);
}
var Person=function (name) {
    this.fullName=name
    console.log(this.fullName)
}
var chandra=new Person("chandrakumar")
var kumar=new Person("kumar")
var specificCall=function(){
    console.log("Dude "+ this.fullName);
}
var newGreeting=Person.call.bind(specificCall)// I don't understand the meaning here
newGreeting()// logs Dude 
newGreeting(kumar)//logs Dude kumar How is this happening

I think Person.call is a function as I have checked typeof Person.call and specificCall is a function again. How can I bind a function to a function? Though I wrote this code accidentally I don't understand the logic? Person.call fires the constructor function whereas newGreeting fires the specificCall function. if you look closely newGreeting(kumar) is equivalent to specificCall.apply(kumar). Here the not only context of the scope is changed but the whole function itself. Its like specificCall is bound to Person.call?


Solution

  • Call allows you to set the scope for a functions exection, defaulting to window, while activating it.

    //Set global variable to fallback to
    var fullname = "Window";
    //Set local variable
    var person = {
        fullname: "Bob"
    };
    //Definer caller object
    function logObject() {
        //"this" references current scope
        console.log(this.fullname);
    }
    //Call with nothing, defaulting to global
    logObject.call();
    //Call with specific object as scope
    logObject.call(person);

    Bind sets the scope for a function, but doesn't activate it.

    //Set global variable to fallback to
    var fullname = "Window";
    //Set local variable
    var person = {
      fullname: "Bob"
    };
    //Definer caller object
    function logObject() {
      //"this" references current scope
      console.log(this.fullname);
    }
    //Bind with nothing, defaulting to global
    var logger1 = logObject.bind();
    //Execute
    logger1();
    //bind with specific object as scope
    var logger2 = logObject.bind(person);
    //Execute
    logger2();

    As far as i can tell, you bind specificCall to a call on Person, meaning that firing newGreeting is the same as running Person.call but with specificCall as the bound scope.

    It's not pretty code and i would personally recommend a more readable structure:

    var fullName = "window";
    var Person = function (name) {
        this.fullName = name;
    };
    var chandra = new Person("chandrakumar");
    var kumar = new Person("kumar");
    function specificCall(scope) {
        if (scope === void 0) { scope = window; }
        console.log("Dude " + scope.fullName);
    }
    specificCall(); // logs Dude window
    specificCall(kumar); //logs Dude kumar