Suggest an editImprove this articleRefine the answer for “The this keyword”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`this` is a reference to the execution context of a function, that is, to the object in whose context the function was called.** The value of `this` is not decided when the function is declared: it is assigned at call time and depends on how the function is called, not on where it is written. A call through the dot, `obj.method()`, gives `obj` itself; a plain call, `fn()`, gives `undefined` in strict mode and `window` in sloppy mode; a call with `new` gives the freshly created instance; `call`, `apply` and `bind` set `this` explicitly; an event handler receives the DOM element. Arrow functions are the special case: they have no `this` of their own and take it from the surrounding lexical scope. ```javascript const user = { name: 'Oleh', sayHi() { console.log(this.name); } }; user.sayHi(); // 'Oleh', called through the dot const fn = user.sayHi; fn(); // undefined, the context is lost fn.call(user); // 'Oleh', this is set explicitly ``` **Key point:** `this` is decided by the call site, not by the declaration site, except in arrow functions, where `this` is lexical.Shown above the full answer for quick recall.Answer (EN)Image**`this` is a reference to the execution context of a function, that is, to the object in whose context the function was called.** The value of `this` is assigned at call time and depends on how the function is called, not on where it is written. ## Theory ### TL;DR - `this` is not fixed when a function is declared, it is assigned at runtime, at the moment of the call. - A call through the dot, `obj.method()`, binds `this` to `obj`. - A plain call, `fn()`, gives `undefined` in strict mode and `window` in sloppy mode. - `new` creates a fresh object and makes it the value of `this`. - `call`, `apply` and `bind` set `this` explicitly. - Arrow functions have no `this` of their own, they inherit it from the surrounding scope. ### Quick example ```javascript function showName() { console.log(this.name); } const user = { name: 'Oleh', showName }; user.showName(); // 'Oleh', the object before the dot showName.call({ name: 'Maria' }); // 'Maria', this is set explicitly const detached = user.showName; detached(); // TypeError in strict mode, the context is lost ``` ### How `this` is determined Put simply: - `this` is not determined when the function is declared; - it is assigned at the moment of the call (runtime); - and it depends on the way the function is called, not on where it is written. **Global context.** Outside any function: ```javascript console.log(this); ``` - in a browser this is `window`; - in Node.js inside a CommonJS module it is `{}`, an empty object (`module.exports`); - in an ES module it is `undefined`. **Inside a plain function.** ```javascript function showThis() { console.log(this); } showThis(); ``` If the function has no "owner", that is, it is not called as `obj.method()`: - in sloppy mode `this` is `window`; - in strict mode (`'use strict'`) `this` is `undefined`. Code inside classes and ES modules is always strict, so the second case applies there. ### Object methods and losing the context When a function is called through the dot, `this` points to the object before the dot: ```javascript const user = { name: 'Oleh', sayHi() { console.log(`Hi, I am ${this.name}`); } }; user.sayHi(); // Hi, I am Oleh ``` But the method itself does not "remember" its object. Store a reference to it in a variable and the link is gone: ```javascript const user = { name: 'Oleh', sayHi() { console.log(this.name); } }; const fn = user.sayHi; fn(); // undefined in sloppy mode, TypeError in strict mode ``` The context is lost the same way when a method is passed as a callback: `setTimeout(user.sayHi, 1000)`, `arr.map(user.sayHi)`, `element.addEventListener('click', user.sayHi)`. The function travels on its own, with no object before the dot. ### How to keep `this` **Option 1: `bind`.** It returns a new function with the context attached for good. ```javascript const boundFn = user.sayHi.bind(user); boundFn(); // Hi, I am Oleh setTimeout(boundFn, 1000); // still works ``` **Option 2: an arrow function.** Arrows have no `this` of their own and take it from the outer scope: ```javascript const user = { name: 'Oleh', sayHiLater() { setTimeout(() => { console.log(this.name); // 'Oleh', this comes from sayHiLater }, 1000); } }; user.sayHiLater(); ``` The flip side of the same property: an arrow is a poor object method, because it takes `this` from the declaration site rather than from the call: ```javascript const user = { name: 'Oleh', showThis: () => console.log(this) }; user.showThis(); // window in a browser script, undefined in a module ``` **Option 3: explicit control with `call`, `apply`, `bind`.** | Method | What it does | When it runs | | --- | --- | --- | | `call(thisArg, a, b)` | calls the function with the given `this`, arguments listed one by one | immediately | | `apply(thisArg, [a, b])` | the same, but arguments come as an array | immediately | | `bind(thisArg)` | returns a new function with `this` attached | later | ```javascript function greet() { console.log(`Hi, ${this.name}`); } const user = { name: 'Oleh' }; greet.call(user); // Hi, Oleh greet.apply(user); // Hi, Oleh greet.bind(user)(); // Hi, Oleh ``` ### `new`, classes and event handlers **Calling with `new`.** If a function is called with `new`, `this` points to the newly created object: ```javascript function User(name) { this.name = name; } const oleh = new User('Oleh'); console.log(oleh.name); // Oleh ``` What happens during a `new` call: 1. an empty object `{}` is created; 2. it is bound to `this`, and its prototype is set to `User.prototype`; 3. the function body runs; 4. that object is returned, unless the function explicitly returns another object. **In classes** `this` behaves exactly as in ordinary object methods: ```javascript class User { constructor(name) { this.name = name; } sayHi() { console.log(`Hi, I am ${this.name}`); } } const oleh = new User('Oleh'); oleh.sayHi(); // Hi, I am Oleh ``` **In event handlers** in the browser, `this` points to the DOM element the listener is attached to: ```javascript button.addEventListener('click', function () { console.log(this); // the button element }); ``` Pass an arrow function instead and `this` is no longer the button, it is the outer context: ```javascript button.addEventListener('click', () => { console.log(this); // not the button, but the outer context }); ``` In that case use `event.currentTarget`, which is more reliable than `this` and behaves the same for both kinds of functions. ### Summary table | Context | What `this` holds | | --- | --- | | Global (in a browser) | `window` | | In a plain function | `undefined` in strict mode, `window` in sloppy mode | | In an object method | The object itself | | In an arrow function | The `this` of the outer scope | | In a constructor or class | The new instance | | In an event handler | The DOM element the listener sits on | | Through `call`, `apply`, `bind` | The object you passed in | ### Common mistakes - Assuming `this` depends on where the function is declared. For ordinary functions the call site decides. - Passing a method as a callback without binding: `setTimeout(user.sayHi, 1000)`. Use `user.sayHi.bind(user)` or an arrow, `() => user.sayHi()`. - Using an arrow as an object method and then wondering why `this.name` is `undefined`. - Attaching an arrow with `addEventListener` and expecting `this` to be the element. Use a regular function or `event.currentTarget`. - Forgetting `new` when calling a constructor function. In strict mode you get a `TypeError`, in sloppy mode the properties land on the global object. - Trying to rebind an already bound function. A second `bind`, or `call` applied to the result of `bind`, does not change the context.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.