JavaScript • Object-Oriented Programming (Intro)

this Binding in Classes — Understand this binding basics in class methods (conceptual)

Learn how the this keyword connects class methods to the object that called them.

JavaScript emblem with code brackets, braces, and a code file.
Inside this lesson 10 sections 5 questions 5 figures

SECTION 1

Historical Context & Motivation

When JavaScript was first created in 1995 by Brendan Eich, it was designed as a simple scripting language for web browsers. However, as websites grew more complex, developers needed a way to organize code into reusable blueprints — much like how a cookie cutter lets you stamp out identical cookies. The concept of object-oriented programming (OOP) provided that blueprint system, and the this keyword became the glue that connected each object to its own data.

Early JavaScript used functions and prototypes to simulate classes, which made this behavior confusing for newcomers. Developers often lost track of what this referred to, leading to bugs that were notoriously hard to find. The introduction of the class syntax in ES6 (2015) gave JavaScript a cleaner, more predictable way to work with objects and this.

1995 • JavaScript Is Born

Brendan Eich creates JavaScript in just 10 days. The this keyword is included from the start, borrowed from languages like Java and C++.

2009 • ES5 Introduces strict mode

ECMAScript 5 adds strict mode, which changes how this behaves in certain situations, making it undefined instead of the global object when unbound.

2015 • ES6 Class Syntax Arrives

The class keyword provides a clean syntax for creating objects. The constructor method and this become more intuitive for beginners.

2022 • Class Fields Become Standard

Public and private class fields, along with arrow-function class properties, offer new ways to handle this binding automatically.

The central question this lesson addresses is: When a method runs inside a class, how does JavaScript know which object's data to use? Understanding this is the key to answering that question.

SECTION 2

Core Principles & Definitions

Before diving into code, you need a solid grasp of a few foundational ideas. The this keyword in JavaScript is a special reference that points to the current object — the object that is "owning" or invoking the method at the moment the code runs. Think of it as a name badge that each object wears: when a method looks at this, it reads the badge to find out whose data to work with.

1

this Is Context-Dependent

The value of this is not fixed when you write the code. It is determined at call time — the moment a function is invoked.
2

The Constructor Sets Up this

Inside a class constructor(), this refers to the brand-new object being created by the new keyword.
3

Dot Notation Binds this

When you call myObj.greet(), JavaScript automatically sets this inside greet to myObj. This is called implicit binding.
4

Losing this Is Common

If you detach a method from its object (e.g., store it in a variable), this can become undefined or point to the wrong thing. This is the #1 source of this-related bugs.
✦

KEY TAKEAWAY

Think of this like the word "I" in a conversation. When you say "I'm hungry," everyone knows you are talking about yourself. When your friend says "I'm hungry," the same word refers to a different person. In the same way, this inside a method always refers to whichever object is 'speaking' — that is, whichever object called the method.

SECTION 3

Visual Explanation

The following diagram illustrates how this works when two different objects are created from the same class. Notice how the same method code produces different results because this points to a different object each time.

How this Points to Different Objectsclass Dogconstructor(name) { this.name = name; }bark() { return this.name + " says Woof!"; }new Dog("Rex")new Dog("Luna")dog1 (Object)name: "Rex"bark: [Function]dog2 (Object)name: "Luna"bark: [Function]dog1.bark()this → dog1"Rex says Woof!"dog2.bark()this → dog2"Luna says Woof!"Same class, same method code → different this → different output
Both dog1 and dog2 share the same bark() method from the Dog class, but this points to whichever object called the method (cyan for dog1, pink for dog2), producing different outputs.

In the diagram above, the class Dog acts like a template at the top. When we create dog1 with new Dog("Rex"), JavaScript runs the constructor, and this.name stores "Rex" inside that specific object. The same constructor runs again for dog2, and this time this.name stores "Luna". When each object calls bark(), the dot before bark() tells JavaScript which object this should point to.

SECTION 4

How this Binding Works Step by Step

JavaScript uses a set of rules to determine the value of this. In the context of classes, the two most important rules are new binding (used by the constructor) and implicit binding (used when calling methods with dot notation). Let's walk through each rule.

Rule 1: new Binding (Constructor Calls)

When you write const car = new Vehicle("Toyota"), JavaScript performs four hidden steps behind the scenes: it creates a brand-new empty object, sets this to point to that new object, runs the constructor code which attaches properties to this, and finally returns the new object. You never see these steps in your code, but they happen every time you use new.

Rule 2: Implicit Binding (Dot-Notation Calls)

After an object is created, you call its methods using dot notation like car.start(). The rule is straightforward: the object to the left of the dot becomes this. So in car.start(), this equals car. This is the most common pattern you'll see.

The Danger: Losing this

The binding breaks if you pull a method off its object. Consider const fn = car.start; followed by fn(). There is no dot, no object on the left, so JavaScript can't figure out what this should be. In strict mode (which classes use by default), this becomes undefined, and your code throws an error.

⚠

Remember

Class bodies automatically run in strict mode. This means that if this isn't properly bound, it will be undefined rather than silently pointing to the global window object. This is actually helpful because it makes bugs louder and easier to catch!

SECTION 5

The Four Binding Rules at a Glance

While this lesson focuses on class methods, it helps to see all four this binding rules side by side. Each rule has a different priority level, and JavaScript checks them in order from highest to lowest. In class-based code, you'll mostly encounter the top two.

The this Binding Priority LadderHighest priority at the top1. new Binding (Highest Priority)const obj = new MyClass();this → the brand-new object being created★2. Explicit Bindingfunc.call(obj) / func.bind(obj)this → the object you manually pass in3. Implicit Bindingobj.method();this → the object to the left of the dot★4. Default Binding (Lowest Priority)func(); // no dot, no new, no bindthis → undefined (strict mode) or window (sloppy mode)UsedinclassesUsedinclasses
The priority ladder shows all four binding rules. In class-based JavaScript, you'll primarily encounter new binding (in the constructor) and implicit binding (when calling methods), marked with stars.
RuleCode PatternWhat this EqualsCommon in Classes?
new Bindingnew MyClass()The new objectYes — constructor
Explicit Bindingfn.call(obj)The passed-in objectSometimes (advanced)
Implicit Bindingobj.method()Object before the dotYes — method calls
Default Bindingfn()undefinedBug scenario

The four this binding rules, ranked by priority

SECTION 6

Worked Example: Tracing this Through a Class

Let's trace this step by step through a complete class. We'll define a Student class with a constructor and two methods, then see exactly what this points to at each stage.

Tracing this in a Student Class

  1. 1

    Step 1 — Define the Class

    We start by writing our class definition. At this point, no object exists yet, and this has no value because no instance has been created. class Student { constructor(name, grade) { this.name = name; this.grade = grade; } introduce() { return `Hi, I'm ${this.name} in grade ${this.grade}.`; } isUpperclassman() { return this.grade >= 11; } }
  2. 2

    Step 2 — Create an Instance with new

    We call const alice = new Student("Alice", 11); — the new keyword triggers new binding. JavaScript creates a fresh empty object and sets this to that object. The constructor then attaches this.name = "Alice" and this.grade = 11.
    alice is now { name: "Alice", grade: 11 }
  3. 3

    Step 3 — Call a Method with Dot Notation

    We run alice.introduce(); — the dot before introduce triggers implicit binding. JavaScript sees alice to the left of the dot and sets this = alice. Inside the method, this.name evaluates to "Alice" and this.grade evaluates to 11.
    Returns: "Hi, I'm Alice in grade 11."
  4. 4

    Step 4 — Create a Second Instance

    We create const bob = new Student("Bob", 9); — a completely separate object is created. Now when we call bob.introduce(), this points to bob, not alice. The same method code produces different output.
    Returns: "Hi, I'm Bob in grade 9."
  5. 5

    Step 5 — Watch this Get Lost

    If we write const detached = alice.introduce; and then call detached(); without a dot, there is no object to the left. Since class code runs in strict mode, this becomes undefined, and trying to read this.name throws a TypeError.
    Error: Cannot read properties of undefined (reading 'name')

SECTION 7

Regular Methods vs. Arrow Functions in Classes

As you start working with classes, you'll encounter two styles of defining methods: regular methods (the default) and arrow function class fields. Each handles this differently, and understanding the trade-offs will save you hours of debugging.

FeatureRegular MethodArrow Function Field
Syntaxgreet() { ... }greet = () => { ... }
Where this comes fromDetermined at call time (who calls it)Captured at creation time (always the instance)
Can lose this?Yes — if detached from the objectNo — permanently bound to the instance
Shared on prototype?Yes — one copy shared by all instances (memory efficient)No — each instance gets its own copy
Best forMost class methodsEvent handlers, callbacks

Comparing this behavior in regular methods vs. arrow function class fields

✦

KEY TAKEAWAY

Think of a regular method like a free agent who works for whoever hires them — they look at the dot to figure out their employer. An arrow function field is like an employee with a permanent contract — no matter who calls them, they always work for the same boss (the original instance). Both approaches are valid, and knowing when to use each is a skill you'll build over time.

SECTION 8

Connection to Advanced Patterns

The this binding concepts you've learned here are the foundation for several advanced JavaScript patterns. As you progress, you'll encounter scenarios where this plays an even more central role.

What You Learned TodayWhere It Leads Next
this in constructorsInheritance with extends and super() — the parent constructor sets up part of this
Implicit binding (dot notation)Method chaining — return this at the end of methods enables obj.move().rotate().scale()
Losing this (detaching methods)React class components — event handlers must be bound in the constructor or use arrow functions
Arrow functions capture thisClosures and higher-order functions — understanding scope and context deeply

How today's concepts connect to advanced topics

Don't worry about mastering these advanced patterns yet. The key point is that every advanced this pattern builds on the same four binding rules you've already learned. Once these basics feel natural, the advanced topics will click much faster.

SECTION 9

Practice Problems

Question 1: CONCEPTUAL

In a JavaScript class, what does the keyword this refer to inside a method when you call it using dot notation, like myObj.doSomething()? Explain in your own words why two different objects created from the same class can produce different results from the same method.
Show answer
When you call a method using dot notation, this refers to the object on the left side of the dot — in this case, myObj. This is called implicit binding. Two different objects created from the same class have different property values stored inside them (for example, different names or scores). Since this points to a different object each time, this.name reads different data, which is why the same method produces different results.

Question 2: BASIC CALCULATION

Consider the following code: class Counter { constructor(start) { this.count = start; } increment() { this.count += 1; return this.count; } } If you write const c = new Counter(5); c.increment(); c.increment();, what is the final value of c.count?
Show answer
The final value of c.count is 7. The constructor sets this.count = 5. The first call to c.increment() uses implicit binding so this is c, and this.count goes from 5 to 6. The second call increments it again from 6 to 7.

Question 3: INTERMEDIATE

Look at this code: class Greeter { constructor(name) { this.name = name; } greet() { return `Hello, ${this.name}!`; } } const g = new Greeter("Sam"); const myFunc = g.greet; myFunc(); What happens when myFunc() is called? Explain which binding rule applies and why the result is different from calling g.greet().
Show answer
Calling myFunc() throws a TypeError. When we assign g.greet to myFunc, we detach the function from the g object. Calling myFunc() has no dot and no object on the left, so the default binding rule applies. Since class code runs in strict mode, this becomes undefined, and reading undefined.name causes the error. By contrast, g.greet() uses implicit binding where this is g, returning "Hello, Sam!".

Question 4: APPLIED

You're building a simple game. You have a Player class: class Player { constructor(name, hp) { this.name = name; this.hp = hp; } takeDamage(amount) { this.hp -= amount; return `${this.name} has ${this.hp} HP left.`; } } You create const hero = new Player("Aria", 100) and const villain = new Player("Drax", 80). You then call hero.takeDamage(25) and villain.takeDamage(30). What does each call return, and why doesn't one call affect the other player?
Show answer
hero.takeDamage(25) returns "Aria has 75 HP left." because this is bound to hero via implicit binding — hero is to the left of the dot. villain.takeDamage(30) returns "Drax has 50 HP left." because now this is bound to villain. Each call doesn't affect the other player because this points to separate objects with their own hp property.

Question 5: CRITICAL THINKING

A classmate argues: "Arrow functions are always better in classes because you never lose this." Evaluate this claim. What is one advantage of arrow function class fields over regular methods, and what is one disadvantage? When would you choose a regular method instead?
Show answer
The claim is partially correct but oversimplified. The advantage of arrow function class fields is that this is permanently bound to the instance at creation time, so you can safely pass them as callbacks (e.g., to event listeners) without worrying about losing this. The disadvantage is that each instance gets its own copy of the function, which uses more memory — if you create 1,000 objects, you get 1,000 copies. Regular methods are stored once on the prototype and shared by all instances, making them more memory-efficient. You should choose a regular method when you don't plan to detach it, which is the majority of cases. Arrow fields are best reserved for methods you know will be passed around as callbacks.

SUMMARY

Lesson Summary

Summary

The this keyword in JavaScript is a dynamic reference that points to the object executing the current method. Inside a class constructor, the new binding rule applies: this refers to the brand-new object being created. When calling a method using dot notation (like obj.method()), the implicit binding rule makes this point to the object to the left of the dot. This is why the same method code can produce different results for different objects.

A common pitfall is losing this by detaching a method from its object (storing it in a variable and calling it without a dot). In strict mode (which classes use by default), an unbound this becomes undefined. Arrow function class fields offer one solution by permanently binding this at creation time, though they trade off memory efficiency. Understanding these binding rules is the essential first step toward mastering object-oriented JavaScript.

Varsity Tutors • JavaScript • this Binding in Classes