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
this keyword is included from the start, borrowed from languages like Java and C++.2009 • ES5 Introduces strict mode
this behaves in certain situations, making it undefined instead of the global object when unbound.2015 • ES6 Class Syntax Arrives
class keyword provides a clean syntax for creating objects. The constructor method and this become more intuitive for beginners.2022 • Class Fields Become Standard
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.
this Is Context-Dependent
this is not fixed when you write the code. It is determined at call time — the moment a function is invoked.The Constructor Sets Up this
constructor(), this refers to the brand-new object being created by the new keyword.Dot Notation Binds this
myObj.greet(), JavaScript automatically sets this inside greet to myObj. This is called implicit binding.Losing this Is Common
this can become undefined or point to the wrong thing. This is the #1 source of this-related bugs.KEY TAKEAWAY
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.
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
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.
| Rule | Code Pattern | What this Equals | Common in Classes? |
|---|---|---|---|
| new Binding | new MyClass() | The new object | Yes — constructor |
| Explicit Binding | fn.call(obj) | The passed-in object | Sometimes (advanced) |
| Implicit Binding | obj.method() | Object before the dot | Yes — method calls |
| Default Binding | fn() | undefined | Bug 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
Step 1 — Define the Class
We start by writing our class definition. At this point, no object exists yet, andthishas 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
Step 2 — Create an Instance with new
We callconst alice = new Student("Alice", 11);— thenewkeyword triggers new binding. JavaScript creates a fresh empty object and setsthisto that object. The constructor then attachesthis.name = "Alice"andthis.grade = 11.aliceis now{ name: "Alice", grade: 11 } - 3
Step 3 — Call a Method with Dot Notation
We runalice.introduce();— the dot beforeintroducetriggers implicit binding. JavaScript seesaliceto the left of the dot and setsthis = alice. Inside the method,this.nameevaluates to "Alice" andthis.gradeevaluates to 11.Returns:"Hi, I'm Alice in grade 11." - 4
Step 4 — Create a Second Instance
We createconst bob = new Student("Bob", 9);— a completely separate object is created. Now when we callbob.introduce(),thispoints tobob, notalice. The same method code produces different output.Returns:"Hi, I'm Bob in grade 9." - 5
Step 5 — Watch this Get Lost
If we writeconst detached = alice.introduce;and then calldetached();without a dot, there is no object to the left. Since class code runs in strict mode,thisbecomesundefined, and trying to readthis.namethrows aTypeError.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.
| Feature | Regular Method | Arrow Function Field |
|---|---|---|
| Syntax | greet() { ... } | greet = () => { ... } |
| Where this comes from | Determined at call time (who calls it) | Captured at creation time (always the instance) |
| Can lose this? | Yes — if detached from the object | No — 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 for | Most class methods | Event handlers, callbacks |
Comparing this behavior in regular methods vs. arrow function class fields
KEY TAKEAWAY
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 Today | Where It Leads Next |
|---|---|
this in constructors | Inheritance 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 this | Closures 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
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
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
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
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
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
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
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
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
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.