Is JavaScript function invocation confusing?

Answer will be…

  • Yes for those “Who don’t understand the core primitive of JavaScript function”.
  • No for those “Who understands the core primitive”.

So, what is “Core Primitive In JavaScript Function Invocation”?

Lets start

When we write a JavaScript function, we do following things…

  1. Create function
  2. Creating the argument list from arg1 till end
  3. Then call that function
  4. Code

    function greet(thing) {
        console.log(this + 'says hello '+ thing);
    } 
    
    greet.call('Maddy', 'world';);

    Output

    Maddy says hello world

    Explanation:

    So, here you can see that function argument are two when we call, but there is only one argument in function definition. In JavaScript function, the first argument acts as this, and then others are as argument.
    Let’s understand it by calling the above differently.
    If we call the same function as

    greet.call('Maddy');

    Output

    Maddy says hello undefined

    NOTE : It will take the first argument as this.
    Obviously calling a JavaScript function with .call() is bit annoying. So JavaScript allows us to call directly.
    So when we call it like

    Code

    greet('Maddy');

    Output

    [object Window] says hello Maddy

    Basically, what it dose is, when we call like the last way

    greet('Maddy');

    Then JavaScript takes it it like…

    greet.call(window, 'world');

    Member Function Invocation

    When we create a object and add a function as a member, and call that function then it act as differently.
    Like it take that created object as the default parameter.

    Code

    var person = {
        name:'Maddy',
        greet: function (thing) {
                console.log(this + ' says hello ' + thing);
        }
    };
    
    // this:
    person.greet('world'); // Output - [object Object] says hello world
     
    // takes it to this:
    person.greet.call(person, 'world'); // Output- [object Object] says hello world
    

    It doesn’t actually matter how that method is being attached.
    Let’s see what happens when we attach it dynamically:
    Now we will attach a method to an object dynamically.

    function greet(thing) {
        console.log(this + ' says hello' + thing);
    }
    
    person = { name: 'mac' }
    person.greet = greet;
     
    person.greet('world') // act as person.greet.call(person, "world")
    greet('world') // '[object DOMWindow]world';
    

    Here what the conclusion on above:

    • Function doesn’t have a persistent value of its ‘this’.
      • It is always set at call time based upon the way it was invoked by its caller.

      Function.prototype.bind

      Yes, it can help us having a persistent value of “this” with reference to a function.
      So with some minor “closure” tricks we can make the value of “this” persistent.

      // define the object 
      var person = {
      	name: 'Mac',
      	greet: function(thing) {
      		return  (this.name + ' says hello ' + thing);
      	}
      }
      
      var boundHello = function(thing) { 
      	return person.greet.call(person, thing);  // Here the use of call method to change the value of "this"
      }
      
      alert(boundHello('world')); // Output- Mac says hello world.
      

      Here it in more generic fashion:

      var person = {
      	name: 'Brendan Eich',
      	greet: function(thing) {
      		console.log(this.name + ' says hello ' + thing);
      	}
      }
      
      var bind = function(func, thisValue) {
      	return function() {
      		return func.apply(thisValue, arguments); //more generic using apply() method
      	}
      }
       
      var boundHello = bind(person.greet, person);
      boundHello('world');// 'Mac says hello world';
      

      In the above code the bind method returns a new function by invoking original function.

      Bind is useful

      var person = {
      	name: 'Mac',
      	greet: function(thing) {
      		console.log(this.name + ' says hello ' + thing);
      	}
      }
      
      var boundHello = person.greet.bind(person); // it bind person object to the greet method
      boundHello('world') // 'Mac says hello world';
      

      Also, if you want to directly call it on dom operation

      var person = {
      	name: 'Mac',
      	greet: function() { console.log(this.name + ' says hello world'); }
      }
      	 
      $('#some-div').click(person.greet.bind(person)); 
      // raw function to pass as a callback: 
      // Output - Mac says hello world
      

      NOTE :
      jQuery uses these call and apply methods internally to set the this value to other than window.

      Conclusion

      This is an extremely powerful thing but it makes an wrong impression on beginners as this is very strange.But if we carefully understand the core primitive of javascript functions, and its invocation we can use it many ways.

      Thanks for reading 🙂

Leave a comment