Frontend Development 13 min read

Mastering JavaScript’s this: When, Why, and How It Changes

This article provides a comprehensive, step‑by‑step explanation of JavaScript’s this binding, covering execution context, global and function scopes, strict mode nuances, call/apply usage, and constructor behavior, all illustrated with clear diagrams and code examples.

Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Mastering JavaScript’s this: When, Why, and How It Changes

When learning JavaScript, we often form vague or inaccurate conclusions about concepts like

this

, which then spread online and cause confusion.

One common misconception is “whoever calls a function,

this

points to that caller.” This works in some cases but fails in many, leading to puzzling bugs.

Search results on Baidu often contain incorrect knowledge that misleads developers for a long time.

Therefore, a thorough article is needed to give a correct, complete understanding of

this

. First, we review the execution context.

In previous posts I described the lifecycle of an execution context; the diagram below summarizes it.

During the creation phase, a variable object, a scope chain, and the

this

binding are established. The crucial point is that

this

is determined when the function is called, i.e., when the execution context is created. Consequently, the same function can have different

this

values depending on how it is invoked.

Once

this

is fixed during execution, it cannot be changed.

1. this in the Global Object

In the global environment,

this

points to the global object itself, which makes it relatively simple.

2. this in Functions

To feel the unpredictability of

this

inside functions, consider the following strange examples.

Conclusion: In a function context,

this

is provided by the caller. If the caller is an object that owns the function,

this

points to that object; if the function is called independently,

this

is

undefined

(or the global object in non‑strict mode).

For example:

fn()

– independent call,

this

is

undefined

.

window.fn()

– the function belongs to

window

, so

this

points to

window

.

In demo03,

obj.c

uses

this.a + 20

, but

obj.c

is not a function, so the previous rule does not apply. The rule is:

When

obj

is declared globally, any use of

obj.c

has

this

bound to the global object; when

obj

is declared inside a function,

this

is

undefined

(or the global object in non‑strict mode).

In real development, this pattern is not recommended. Strict mode is essential; most modern codebases already use it, and ES6 defaults to strict mode.

Additional examples reinforce the distinction between a caller that owns the function and an independent call.

foo.getA()

getA

is owned by

foo

, so

this

points to

foo

.

test()

– independent call,

this

is

undefined

(or

window

in non‑strict mode).

Further code modifications illustrate the same principle.

3. Using call and apply to Explicitly Set this

JavaScript provides

call

and

apply

to manually set the

this

binding. Both methods belong to every function; the first argument is the object that should become

this

.

Example:

fn

is not a method of

obj

, but

fn.call(obj)

binds

this

inside

fn

to

obj

, allowing access to

obj.a

.

The arguments after the first are passed to the target function:

call

passes them one by one, while

apply

passes an array. This difference enables many useful scenarios:

1. Convert array‑like objects to true arrays

2. Flexibly modify the this binding

3. Implement inheritance

In a constructor like

Student

,

Parent.call(this)

copies the parent’s initialization code and ensures

this

points to the new

Student

instance.

4. Preserve this when passing functions between contexts

When a callback loses its original

this

, we can store the reference in a variable, use

bind

, or apply

call/apply

to restore it.

Common solution: assign

var self = this

before entering the inner function, or use

Function.prototype.bind

(available natively in ES5).

ES5’s built‑in

bind

method achieves the same effect.

4. this in Constructors and Prototype Methods

When using

new

, the process involves four steps:

1. Create a new empty object.

2. Bind the constructor’s

this

to that new object.

3. Execute the constructor code, adding properties and methods to the object.

4. Return the new object.

Thus, inside a constructor,

this

refers to the newly created instance (e.g.,

p1

).

For prototype methods, the rule is the same: the method’s

this

points to the object that invoked it, such as

p1.getName()

where

this

is

p1

.

In summary, mastering the binding rules of

this

, understanding strict mode, and leveraging

call

,

apply

, and

bind

will help you avoid common pitfalls and write more predictable JavaScript code.

JavaScriptthis keywordExecution ContextapplyCALL
Tencent IMWeb Frontend Team
Written by

Tencent IMWeb Frontend Team

IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.