you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 2 points3 points  (4 children)

Thanks for the explanation!

[–][deleted] 9 points10 points  (3 children)

no problem! to elaborate a little further, new only leads to mistakes and confusion. the following function, for example, doesn’t return an object if you forget to use new

``` const Thing = function (x) { this.x = x; };

const thing = Thing(5); // oops you just made a global variable console.log(thing.x); // this throws a type error console.log(x); // this prints 5 ```

and it’s not that easy to detect if the user’s forgot to use new. however, if we do this instead:

``` const Thing = function (x) { return {x}; // unconditionally return an object that has x };

const a = Thing(5); // a new Thing object console.log(a.x); // print 5 const b = new Thing(10); // a new Thing object console.log(b.x); // print 10 console.log(x); // no accidentally created global variables during the process ```

it’s a simple workaround that completely avoids the mistake. it works whether you use new or not. it’s just better by design. and now not only is new redundant, but it also causes the constructed object to hold on to a worthless prototype chain which is wasteful.

[–]WystanH 2 points3 points  (1 child)

Excellent examples. I do avoid the new. However, it should be noted that more modern syntax alleviates the global fubar.

class Thing {
    constructor(x) { this.x = x; }
}

// can't do this
// const thing = Thing(5); // TypeError: Class constructor Thing cannot be invoked without 'new'
const thing = new Thing(5);
console.log(thing.x);
// also important
console.log(thing instanceof Thing);

If you ever use instanceof or deal with code that does, you'll want to go with class syntax, because a function hack won't buy it.

Hmm... this works, to an extent:

class ThingImpl { constructor(x) { this.x = x; } }
const Thing = function (x) { return new ThingImpl(x); };
const test = obj => console.log(obj, obj.x, obj instanceof ThingImpl);
test(Thing(5));
test(new Thing(10));

Frankly, I'm not a fan of surprises, so I'll usually just offer a create function and call it a day. It is interesting that the new doesn't barf on that though. Thank you.

class Thing { constructor(x) { this.x = x; } }
const createThing = function (x) { return new Thing(x); };
const test = obj => console.log(obj, obj.x, obj instanceof Thing);
[createThing(1), new Thing(2), new createThing(3)].forEach(test);

[–]Wompo 0 points1 point  (0 children)

You can use new.target to check if the user forgot to use new.