Skip to content

Function Invocation

JavaScript functions are not executed when they are defined, but when they are invoked (or called). The way a function is invoked determines the value of its this keyword, among other things.

There are several ways to invoke a function, each with implications for this and behavior.

In JavaScript, this is a special keyword whose value is determined by how a function is called (its execution context). It refers to the object that is currently “owning” or “executing” the code.

The value of this is not static; it’s dynamic and depends on the invocation context.

this is a keyword, not a variable. Its value cannot be directly assigned.

Code inside a function executes only when the function is invoked. Let’s explore the primary invocation patterns:

1. Invoking a Function as a Function (Direct Invocation)

Section titled “1. Invoking a Function as a Function (Direct Invocation)”

This is the most straightforward way to call a function.

function multiply(a, b) {
return a * b;
}
const result = multiply(10, 2); // result is 20

this in Direct Invocation:

  • Non-Strict Mode: If a function is called directly (not as a method, constructor, or via apply/call/bind) in non-strict mode, this defaults to the global object. In browsers, this is window. In Node.js, it’s global.
  • Strict Mode: In strict mode ("use strict";), if a function is called directly, this will be undefined. This helps prevent accidental modification of the global object.
function showThis() {
console.log(this);
}
showThis(); // In non-strict browser: Window object. In strict mode: undefined.

Modern JavaScript (ES Modules, classes) often runs in strict mode by default. Relying on this being the global object is generally discouraged as it can lead to hard-to-debug issues and makes code less portable.

2. Invoking a Function as a Method (Method Invocation)

Section titled “2. Invoking a Function as a Method (Method Invocation)”

When a function is a property of an object and is called using that object, it’s a method invocation.

const myObject = {
firstName: "John",
lastName: "Doe",
fullName: function() { // Or using ES6 shorthand: fullName() {
return `${this.firstName} ${this.lastName}`;
}
};
const name = myObject.fullName(); // name is "John Doe"

this in Method Invocation:

In this case, this is set to the object that owns the method (the object used to call the method). In the example above, this inside fullName refers to myObject.

const testObject = {
value: 10,
getValue: function() {
return this.value; // 'this' is testObject
}
};
console.log(testObject.getValue()); // Output: 10

3. Invoking a Function as a Constructor (Constructor Invocation)

Section titled “3. Invoking a Function as a Constructor (Constructor Invocation)”

If a function is called with the new keyword, it’s a constructor invocation. This is used to create new objects.

function Person(firstName, lastName) {
// 'this' refers to the new object being created
this.firstName = firstName;
this.lastName = lastName;
}
const person1 = new Person("Alice", "Wonderland");
// person1 is now { firstName: "Alice", lastName: "Wonderland" }
console.log(person1.firstName); // Output: Alice

this in Constructor Invocation:

  • A new empty object is created.
  • This new object is set as the this binding for the function call.
  • The new object inherits properties and methods from the constructor’s prototype.
  • If the function doesn’t explicitly return an object, the new object (this) is returned automatically.

4. Invoking a Function with call(), apply(), or bind() (Indirect Invocation)

Section titled “4. Invoking a Function with call(), apply(), or bind() (Indirect Invocation)”

JavaScript functions are objects, and they have built-in methods: call(), apply(), and bind(). These methods allow you to invoke a function and explicitly set the value of this, regardless of how or where the function is defined.

call(thisArg, arg1, arg2, ...):

Invokes the function with a specified this value and arguments provided individually.

function greet(greeting, punctuation) {
console.log(`${greeting}, ${this.name}${punctuation}`);
}
const person = { name: "Bob" };
greet.call(person, "Hello", "!"); // Output: Hello, Bob!

apply(thisArg, [argsArray]):

Similar to call(), but arguments are provided as an array (or an array-like object).

greet.apply(person, ["Hi", "..."]); // Output: Hi, Bob...

bind(thisArg, arg1, arg2, ...):

bind() creates a new function that, when called, has its this keyword set to thisArg, and optionally, with a given sequence of arguments preceding any provided when the new function is called.

const greetBob = greet.bind(person, "Hey there");
greetBob("."); // Output: Hey there, Bob.
const greetBobLater = greet.bind(person);
greetBobLater("Good day", "!!"); // Output: Good day, Bob!!

These methods are very powerful for controlling the execution context of functions, especially in callbacks and event handlers.

ES6 arrow functions (=>) behave differently regarding this. An arrow function does not have its own this binding. Instead, it lexically inherits this from its surrounding (enclosing) scope at the time it is defined.

const myObj = {
value: 100,
regularMethod: function() {
console.log("Regular method 'this':", this.value); // 'this' is myObj
setTimeout(function() {
// In this traditional callback, 'this' is window/undefined (in strict mode)
console.log("setTimeout (regular fn) 'this':", this.value); // undefined or error
}, 100);
setTimeout(() => {
// In this arrow function, 'this' is lexically inherited from regularMethod
console.log("setTimeout (arrow fn) 'this':", this.value); // 100
}, 200);
},
arrowMethod: () => {
// 'this' is inherited from the scope where myObj was defined
// NOT myObj itself. Typically window/global or undefined in module scope.
console.log("Arrow method 'this':", this.value); // Likely undefined or error
}
};
myObj.regularMethod();
// myObj.arrowMethod(); // Would show 'this' as not myObj

This lexical this behavior makes arrow functions particularly useful for callbacks and methods where you want to preserve the this value from an outer function scope.

However, arrow functions are generally not suitable for object methods that need to refer to the object instance itself via this, or for constructor functions (they cannot be called with new).

  • Direct Invocation: window/global (non-strict), undefined (strict).
  • Method Invocation: The object owning the method.
  • Constructor Invocation: The newly created instance.
  • call()/apply()/bind(): The explicitly provided thisArg.
  • Arrow Function: Lexically inherited from the surrounding scope.

Understanding these invocation patterns and their effect on this is a cornerstone of JavaScript proficiency.