Suggest an editImprove this articleRefine the answer for “return inside a constructor”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**A constructor returns `this` even without a `return`, and an explicit `return` only matters when it returns an object.** That object replaces the freshly created instance and is what the variable after `new` receives. A primitive (a number, a string, `true`, `null`) is ignored entirely, and `new` still yields `this`. In a class with `extends`, `super()` must be called before any `return`. ```javascript class User { constructor(name) { this.name = name; return { custom: "another object" }; } } console.log(new User("Tim")); // { custom: "another object" } ``` **Key point:** an object returned from a constructor replaces `this`, a primitive is ignored. Singleton and factory patterns rest on exactly this rule.Shown above the full answer for quick recall.Answer (EN)Image**`return` in a constructor exists only to replace the instance being created with a different object.** Without it the constructor implicitly returns `this`, and a returned primitive is simply ignored by the engine. ## Theory ### TL;DR - `return` in a constructor is optional: `this` is returned by default. - If you return an object, it replaces `this` and becomes the result of `new`. - If you return a primitive, it is ignored and the result is still `this`. - In a derived class `super()` must be called before any `return`, otherwise you get a `ReferenceError`. - The Singleton, Factory and Proxy patterns all build on this behaviour. ### Quick example ```javascript class User { constructor(name) { this.name = name; } } const u = new User("Tim"); console.log(u); // User { name: "Tim" } ``` ### The normal behaviour of a constructor When you write `new User("Tim")`, the engine does roughly this: 1. Creates a new empty object `{}`. 2. Sets the prototype of that object to `User.prototype`. 3. Calls the `constructor` with `this` referring to that new object. 4. Returns `this` from the constructor by default. In other words, if you return nothing, `return this` happens implicitly. ### Returning an object replaces this If `return` hands back an object, it replaces the created instance: ```javascript class User { constructor(name) { this.name = name; return { custom: "another object" }; } } const u = new User("Tim"); console.log(u); // { custom: "another object" } ``` Note that `this.name = name` still ran, that object just went nowhere. The returned object has neither `User.prototype` nor the class methods, so `u instanceof User` is `false`. ### Returning a primitive is ignored Numbers, strings, booleans and other primitives cannot overwrite `this`: ```javascript class User { constructor(name) { this.name = name; return 42; } } const u = new User("Tim"); console.log(u); // User { name: "Tim" } ``` There is no error, the value is simply discarded. The same goes for `null`: it is a primitive, so it is ignored too, while `return undefined` changes nothing by definition. ### Why this exists: Singleton and factories The ability to return your own object is there so that a constructor can hand back something special. The classic example is a Singleton, one shared instance for every call: ```javascript class Database { constructor() { if (Database.instance) { return Database.instance; // always hands back the same object } this.connected = true; Database.instance = this; } } const a = new Database(); const b = new Database(); console.log(a === b); // true ``` `return this` is not needed here because the engine does it anyway, while `return Database.instance` substitutes the existing object for the new instance. A constructor that returns different objects depending on its input works the same way: ```javascript class Example { constructor(x) { this.x = x; if (x > 10) return { value: "too large" }; } } console.log(new Example(5)); // Example { x: 5 } console.log(new Example(20)); // { value: "too large" } ``` ### return in derived classes The rule is the same with and without `extends`: a returned object replaces `this`. ```javascript class A {} class B extends A { constructor() { super(); return { name: "replacement" }; } } const b = new B(); console.log(b); // { name: "replacement" } ``` But `super()` stays mandatory even when you return your own object: ```javascript class A {} class B extends A { constructor() { // error, even though there is a return return { test: 1 }; } } new B(); // ReferenceError: Must call super constructor before returning from derived constructor ``` **All the rules in one place:** | Scenario | What comes back | | --- | --- | | No `return` | `this`, the created instance | | `return this` | the same instance | | `return { ... }` | that object instead of `this` | | `return 42` / `"hi"` / `true` | ignored, `this` is returned | | Derived class without `super()` | an error: `super()` must precede `return` | ### Common mistakes - Returning an object literal "for convenience" and then being surprised that `instanceof` and the class methods are gone: the substituted object has no class prototype. - Expecting `return 42` to make `new User()` a number. Primitives from a constructor are ignored with no warning at all. - An early `return` in a derived constructor before `super()`. That is a `ReferenceError`, not a quiet exit. - A Singleton written as `return Database.instance` with heavy initialisation happening before that check: the work is done again and then thrown away. - Confusion around `null`: it is a primitive, so `new` yields `this`, not `null`.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.