JavaScript this Keyword
this is a special word that points to an object. Which object it points to depends on how a function is called, not where it was written.
this in a Method
When a function is called as a method, with object.method(), this is the object before the dot. You saw this in the objects lesson.
Example
const student = {
name: "Bilal",
fee: 4000,
describe() {
return this.name + " pays Rs " + this.fee;
}
};
console.log(student.describe());Bilal pays Rs 4000
describe() {} is a short way of writing describe: function () {}.
The Rules in One Table
| How the function is called | Value of this |
|---|---|
obj.method() | obj |
A plain call: myFunction() | undefined in strict mode and modules, the global window object otherwise |
new MyClass() | The new object being created |
| Inside an arrow function | The this of the code around it |
| In an event listener (normal function) | The element the listener is on |
fn.call(obj), fn.apply(obj), fn.bind(obj) | obj |
Losing this
A common bug: you take a method out of its object and call it on its own. The "object before the dot" is gone, so this is lost.
Example
"use strict";
const shop = {
name: "Saima Boutique",
welcome() {
return "Welcome to " + this.name;
}
};
console.log(shop.welcome()); // works
const fn = shop.welcome;
try {
console.log(fn()); // no object before the dot
} catch (error) {
console.log("Error:", error.message);
}Welcome to Saima Boutique Error: Cannot read properties of undefined (reading 'name')
This often happens when you pass a method to setTimeout or addEventListener.
bind, call and apply
These three methods let you choose this yourself:
fn.call(obj, a, b)runsfnnow, withthis = objfn.apply(obj, [a, b])is the same, but the arguments are in an arrayfn.bind(obj)does not run anything. It returns a new function withthisfixed toobj
Example
<!DOCTYPE html>
<html>
<body>
<p id="demo"></p>
<script>
function introduce(city, course) {
return this.name + " from " + city + " studies " + course;
}
const ali = { name: "Ali" };
const sana = { name: "Sana" };
const lines = [
introduce.call(ali, "Karachi", "Python"),
introduce.apply(sana, ["Multan", "Graphic Design"])
];
const sanaIntro = introduce.bind(sana);
lines.push(sanaIntro("Multan", "UI/UX"));
document.getElementById("demo").innerHTML = lines.join("<br>");
</script>
</body>
</html>Try it Yourself »Ali from Karachi studies Python Sana from Multan studies Graphic Design Sana from Multan studies UI/UX
Arrow Functions Have No Own this
An arrow function does not create its own this. It uses the this of the place where it was written. This makes arrows perfect for callbacks inside a method:
Example
<!DOCTYPE html>
<html>
<body>
<p id="demo">Starting...</p>
<script>
const timer = {
seconds: 3,
start() {
const id = setInterval(() => {
// the arrow uses start()'s this, which is the timer object
document.getElementById("demo").textContent = "Class starts in " + this.seconds + "...";
this.seconds--;
if (this.seconds < 0) {
clearInterval(id);
document.getElementById("demo").textContent = "Class has started!";
}
}, 1000);
}
};
timer.start();
</script>
</body>
</html>Try it Yourself »If you used function () {} inside setInterval, this would not be the timer, and this.seconds would not work.
Because arrows do not have their own this, do not use an arrow function as an object method. this inside it would not be the object.
Example
const box = {
size: 10,
bad: () => typeof this, // this comes from outside the object
good() { return this.size; }
};
console.log(box.good()); // 10this in Event Listeners
With a normal function, this inside a listener is the element the listener was added to (the same as event.currentTarget). With an arrow function, it is not, so use event.currentTarget instead.
Example
<!DOCTYPE html>
<html>
<body>
<button>Small</button>
<button>Medium</button>
<button>Large</button>
<p id="demo"></p>
<script>
document.querySelectorAll("button").forEach(btn => {
btn.addEventListener("click", function () {
document.getElementById("demo").textContent = "You picked size: " + this.textContent;
});
});
</script>
</body>
</html>Try it Yourself »Exercise
Exercise
What does bind() do?
