Understanding this and Closures in JavaScript: A Complete Developer Guide

Master two of the most important JavaScript concepts: this and Closures. Learn lexical scope, dynamic context, Arrow Functions, callbacks, and asynchronous behavior with practical examples.

Author: hamza ougjjou
Published: May 24, 2026
Reading time: 4 min read
Understanding this and Closures in JavaScript: A Complete Developer Guide

Understanding this and Closures in JavaScript

Two JavaScript concepts separate junior developers from advanced engineers:

  • Closures
  • this

Both concepts appear related to function context, but internally they work in completely different ways.

  • Closures depend on where functions are created.
  • this depends on how functions are called.

What Are Closures?

Closures allow functions to remember variables from their outer lexical scope even after the outer function finishes execution.


function outer() {

    const message =
        'Hello';

    function inner() {

        console.log(message);
    }

    return inner;
}

const fn = outer();

fn();

Even though outer() already finished executing, the inner function still remembers the variable.

Lexical Scope

JavaScript uses lexical scoping.

This means functions can access variables based on where they were written in the source code.


function parent() {

    const value = 10;

    function child() {

        console.log(value);
    }

    child();
}

The child function can access variables from its parent scope automatically.

The Famous setTimeout Loop Problem

One of the most common JavaScript interview questions involves closures and loops.

Problem with var


for (var i = 1; i <= 3; i++) {

    setTimeout(() => {

        console.log(i);

    }, 1000);
}

The output becomes:


4
4
4

Because var is function-scoped, all callbacks reference the same variable.

Solution with let


for (let i = 1; i <= 3; i++) {

    setTimeout(() => {

        console.log(i);

    }, 1000);
}

Now the output becomes:


1
2
3

Each loop iteration creates a new block-scoped variable.

Understanding this

Unlike closures, this is determined dynamically at runtime.

Do not ask where the function was written. Ask how the function was called.

Default Binding


function test() {

    console.log(this);
}

test();

In strict mode, this becomes undefined.

Implicit Binding


const user = {

    name: 'Alice',

    greet() {

        console.log(this.name);
    }
};

user.greet();

Because the function is called through user, this refers to that object.

Explicit Binding

JavaScript allows developers to manually control this.


function greet() {

    console.log(this.name);
}

const user = {
    name: 'Alice'
};

greet.call(user);

The call() method explicitly defines the value of this.

The new Keyword


function User(name) {

    this.name = name;
}

const user =
    new User('Alice');

The new keyword creates a new object and binds this automatically.

The Classic Lost this Problem


const user = {

    name: 'Alice',

    greet() {

        setTimeout(function() {

            console.log(this.name);

        }, 1000);
    }
};

user.greet();

The callback loses the original object context.

Inside the callback, this no longer refers to user.

Arrow Functions Solve This

Arrow Functions do not create their own this.

Instead, they inherit this lexically from the surrounding scope.


const user = {

    name: 'Alice',

    greet() {

        setTimeout(() => {

            console.log(this.name);

        }, 1000);
    }
};

user.greet();

Now the callback correctly accesses the original object.

Why Arrow Functions Matter

Arrow Functions solved one of the biggest historical problems in JavaScript callback handling.

This is why they became extremely common in React and Node.js applications.

Closures vs this

Closures

  • Based on lexical scope
  • Determined during creation
  • Remember variables
  • Predictable behavior

this

  • Based on invocation
  • Determined during execution
  • Changes dynamically
  • Depends on call-site

Best Practices

  • Prefer let and const
  • Use Arrow Functions for callbacks
  • Understand lexical scope deeply
  • Avoid relying on implicit this
  • Learn closure behavior with async code

Conclusion

Closures and this are two of the most important foundations of modern JavaScript.

Closures explain how functions remember variables.

this explains how functions receive execution context.

Mastering both concepts dramatically improves understanding of asynchronous JavaScript, React, Node.js, and modern frontend architecture.

Advertisement

Comments

No Comments Yet

Be the first to leave a comment.

Related Articles