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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

this keywordExecution Contextapply__call__
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

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.