This is question #5 of Frontend Interview Questions series. If you're looking to level up your preparation or stay updated in general, consider signing up on Frontend Camp.
The this keyword always refers to the current context of a function or script.
this is a confusing topic for most of us (pun intended), but it doesn't have to be. All you need to do is remember some rules.
Following rules, in order of precedence, dictate how value of this is determined during runtime:
If a function is called with the new keyword, this inside the function refers to the newly created object instance.
function Book(title) { console.log(this); this.title = title; console.log(this); } const book1 = new Book('Jungle Book'); // {} // { title: "'Jungle Book' }" console.log(book1.name); // 'Jungle Book'
call(), apply() or bind() can be used to explicitly set the value of this inside a function.
const obj = { name: 'Ben' }; function sayHello() { console.log(`Hello, ${this.name}!`); } const sayHelloToBen = sayHello.bind(obj); sayHelloToBen(); // Hello, Ben! sayHello.call(obj); // Hello, Ben! sayHello.apply(obj); // Hello, Ben!
If a function is a method of an object, then this refers to the object.
const person = { name: 'Ben', logThis: function() { console.log(this); } } person.logThis(); // { name: 'Ben', logThis: fn() }
If a function is invoked in the global context, then this refers to the global object(in non-strict mode) or undefined(in strict mode).
For browsers, the global object is window.
// Browser function showThis() { console.log(this); } showThis(); // Window { open: fn, alert: fn, ... }
When a function is declared in the global context, it becomes a property of the window object. Calling window.showThis() would yield the same result. This is why it's an implicit method invocation. (Refer the rule above this one)
If multiple rules apply, then the rule with higher precedence will apply.
const obj1 = { value: 1, showThis: function() { console.log(this); }, }; const obj2 = { value: 2 }; obj1.showThis.call(obj2); // { value: 2 }
In the example above, two rules are being applied: Method invocation and Explicit binding. As explicit binding has higher precedence, it gets to set the value of this.
Arrow functions don't follow the rules stated above as they don't have a this value of their own. They pick the this value from the parent scope.
const person = { name: 'Ben', showThis: () => { console.log(this); }, showThisWrapped: function() { const arrowFn = () => console.log(this); arrowFn(); } } person.showThis(); // Window { open: fn, alert: fn, ... } person.showThisWrapped(); // { name: 'Ben', showThis: fn, showThisWrapped: fn }
This is why you should avoid using arrow functions for event listeners. Event listeners bind the HTML element to the this value but if the handler is an arrow function, it is not possible.
function Book(title) { console.log(this); this.title = title; console.log(this); } const book1 = new Book('Jungle Book'); // {} // { title: "'Jungle Book' }" console.log(book1.name); // 'Jungle Book'
Like what you just read? Consider joining the waitlist on Frontend Camp ✌️
The above is the detailed content of `this` in JavaScript Explained. For more information, please follow other related articles on the PHP Chinese website!