Suggest an editImprove this articleRefine the answer for “Arrow methods vs regular methods”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**A regular method lives on the class prototype and receives `this` at call time, while an arrow method is an instance field whose `this` is locked onto the object at creation time.** That is why `setTimeout(u.normal, 500)` loses the context and fails with a `TypeError`, while `setTimeout(u.arrow, 500)` works correctly. The price is that an arrow method is recreated for every `new`, so `a1.arrow !== a2.arrow`, it is enumerable and shows up in `Object.keys()`, and it cannot be reached through `super`. Regular methods are cheaper in memory and support inheritance, arrow methods are more convenient as event handlers and callbacks. ```javascript class A { normal() {} arrow = () => {}; } const a1 = new A(), a2 = new A(); console.log(a1.normal === a2.normal); // true, shared on the prototype console.log(a1.arrow === a2.arrow); // false, a new function per instance ``` **Key point:** a regular method is a shared prototype function with dynamic `this`; an arrow method is an own instance field with `this` bound forever.Shown above the full answer for quick recall.Answer (EN)Image**A regular class method is stored on the prototype and receives `this` dynamically, at call time, while an arrow method is an instance field that captures `this` when the object is created and never loses it.** The syntactic difference is tiny, but the consequences for memory, inheritance and callback behaviour are radically different. ## Theory ### TL;DR - A regular method lives in `Class.prototype` and is shared by all instances. - An arrow method is an own property of the instance, a new function for every `new`. - A regular method resolves `this` at call time, an arrow method has it fixed forever. - An arrow method does not lose its context in `setTimeout` or `addEventListener`, a regular one does without `bind`. - `super` works only with regular methods; an arrow field has no access to it. - Arrow methods are enumerable and appear in `Object.keys()`, regular ones do not. ### Quick example ```javascript class User { name = "Maria"; normal() { console.log("normal:", this.name); } arrow = () => { console.log("arrow:", this.name); }; } const u = new User(); setTimeout(u.normal, 500); // TypeError: Cannot read properties of undefined setTimeout(u.arrow, 500); // arrow: Maria ``` `normal()` lost its context because it was called as an ordinary function. `arrow()` kept the context because an arrow function has no `this` of its own, it captures `this` from the instance while the field is being initialised. ### Syntax A regular method: ```javascript class Button { handleClick() { console.log(this.label); } } ``` An arrow method (a method field): ```javascript class Button { handleClick = () => { console.log(this.label); }; } ``` At first sight the only difference is `= () => {}`, but the behaviour is fundamentally different. ### The main difference: how `this` behaves | Method type | How `this` works | | --- | --- | | **Regular method** | `this` is decided at call time (dynamically) | | **Arrow method** | `this` is hard bound to the instance when the object is created | That is exactly why in the example above the regular method throws while the arrow one prints the name. ### Where methods are stored | Method type | Where it is stored | Shared by all instances? | | --- | --- | --- | | **Regular** | In `ClassName.prototype` | Yes | | **Arrow** | In the instance itself (on every object) | No | ```javascript class A { normal() {} arrow = () => {}; } const a1 = new A(); const a2 = new A(); console.log(a1.normal === a2.normal); // true, one method on the prototype console.log(a1.arrow === a2.arrow); // false, each instance has its own ``` Arrow methods are recreated on every `new A()`. This gives `this` its independence, but costs a little in memory and in object creation speed. ### Event handlers and callbacks A regular method loses `this` unless you bind it by hand: ```javascript class Button { constructor() { this.label = "Click me"; document.body.addEventListener("click", this.handleClick); } handleClick() { console.log(this.label); // undefined, the context is lost } } ``` Solution 1: bind it manually. ```javascript document.body.addEventListener("click", this.handleClick.bind(this)); ``` Solution 2 (more modern): use an arrow method. ```javascript class Button { label = "Click me"; handleClick = () => { console.log(this.label); // "Click me" }; } ``` Arrow methods fit React components and event handlers well, where it matters that `this` is not lost. ### Inheritance and overriding Regular methods are easy to override in subclasses, including through `super`: ```javascript class A { greet() { console.log("Hello from A"); } } class B extends A { greet() { super.greet(); // works console.log("Hello from B"); } } ``` With an arrow field this does not work: ```javascript class A { greet = () => console.log("Hello from A"); } class B extends A { greet = () => { super.greet(); // error, there is no super method to call }; } ``` The reason is that arrow methods are created on the instance, not on the prototype, so overriding is just overwriting a field, and the parent version simply is not in the prototype chain. ### Difference in iteration and debugging Regular methods are non-enumerable, so `Object.keys()` does not show them. Arrow methods are ordinary instance properties, so they are enumerable: ```javascript class Example { method() {} arrow = () => {}; } const e = new Example(); console.log(Object.keys(e)); // ['arrow'] ``` This also means arrow fields are copied by spread and `Object.assign`, while prototype methods are not. ### Performance | Criterion | Regular method | Arrow method | | --- | --- | --- | | Memory | 1 function for all | its own function per instance | | Creation speed | Faster | Slower | | `this` context | Lost without `bind` | Always preserved | | Suitable for `super` | Yes | No | | Suitable for callbacks | Needs `bind` | An ideal fit | ### Summary comparison | Feature | Regular method | Arrow method | | --- | --- | --- | | Where it is stored | `Class.prototype` | In the instance | | Shared by all | Yes | No | | `this` behaviour | Depends on the call | Fixed | | `this` lost in callbacks | Possible | No | | `super` support | Yes | No | | Takes part in inheritance | Yes | No | | Performance | Better | Slightly worse | | Use in React and events | Inconvenient | Very convenient | In short: use regular methods when the method is logically shared by all instances and may be overridden; use arrow methods when preserving `this` matters, for example when passing the method as a callback or an event handler. ### Common mistakes - **Making every method an arrow just in case.** That multiplies functions in memory and strips the class of normal inheritance. - **Expecting `super` inside an arrow field.** It is not there, because the field does not live on the prototype. - **Being surprised that `Object.keys(instance)` shows methods.** It shows the arrow fields, because they are enumerable own properties. - **Assuming a regular method will keep `this` on its own.** Without `bind` or an arrow wrapper it loses the context in any callback. - **Confusing the initialisation order.** Arrow fields are created while the instance is being constructed, so in a base class they are not yet available at the time its constructor runs in a subclass. - **Using arrow fields where the method must be mocked or replaced in tests through the prototype.** Patching `Class.prototype.method` has no effect on an arrow field.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.