Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Javascript

Is JavaScript Function Invocation Confusing?

4.67/5 (12 votes)
3 Oct 2014CPOL2 min read 16.5K  
Is JavaScript function invocation confusing

The 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”?

Let's Start

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

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

Code

JavaScript
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 arguments 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:

JavaScript
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

JavaScript
greet('Maddy');

Output

[object Window] says hello Maddy

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

JavaScript
greet('Maddy');

Then JavaScript takes it like…

JavaScript
greet.call(window, "world");

Member Function Invocation

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

Code

JavaScript
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:

JavaScript
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 is what the conclusion on the above is:

  • 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 in 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.

JavaScript
// 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 is in a more generic fashion:

JavaScript
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 functions by invoking the original function.

Bind is Useful

JavaScript
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:

JavaScript
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 a 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 in many ways.

Thanks for reading! :)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)