
Stop Using Constructors in JS (2012) - outdooricon
http://ericleads.com/2012/09/stop-using-constructor-functions-in-javascript/
======
phpnode
"Stop writing prescriptive articles about software development when you're
speaking from a position of ignorance"

There are many reasons to keep on using `new`, the biggest one is probably
performance, `new Foo` will always outperform `Object.create(FooProto)`.

Really though, this kind of article just grinds my gears. There are so few
absolutes in software development, articles like:

    
    
        "You should always X"
      
    
        "Stop doing Y"
    

almost always really mean

    
    
        "I don't actually understand X or Y"

~~~
swartkrans
> the biggest one is probably performance, `new Foo` will always outperform
> `Object.create(FooProto)`.

He's right, `new` is more than 10x faster in Chrome and Firefox for me at
least:

[http://jsperf.com/create-new](http://jsperf.com/create-new)

Why would it `always outperform` though? Seems like an implementation detail.
Object.create should be faster since it doesn't run a constructor.

~~~
phpnode
The ever-wonderful Vyacheslav Egorov has a nice article on this:

[http://mrale.ph/notes/constructor-vs-
objectcreate.html](http://mrale.ph/notes/constructor-vs-objectcreate.html)

------
davedx
No.

Stop over-engineering. YAGNI!

Most JS codebases are light on polymorphism. I think I've used one UI
framework that had any kind of inheritance at all. I've never (ever) had a bug
caused by "forgetting to type new".

Use strict. Lint your code. Use a decent build toolchain. Stop over-
engineering your code unless you have a damn good justification for it.

~~~
couchand
Avoiding the use of 'new' isn't overengineering, it's idiomatic JS.

~~~
davedx
It's dogmatic not idiomatic.

~~~
BinaryIdiot
> It's dogmatic not idiomatic.

That's not accurate; there are actual, technical reasons for avoiding new
hence why some advise against using it.

~~~
phpnode
There are equally valid technical reasons for _using_ `new`, so it's dogma

~~~
BinaryIdiot
> There are equally valid technical reasons for using `new`, so it's dogma

I really don't want to get into this argument but that's not what dogma means.
Dogma is something that comes from an authority as being undeniable but saying
you can't or shouldn't use new isn't undeniable, it's deniable as you said
yourself there are valid reasons for using new.

and now I hate myself. Thanks.

~~~
phpnode
damn, I've been using that word slightly incorrectly for years, and now _I_
hate myself. Thanks.

~~~
BinaryIdiot
Whoa a pleasant exchange on the internet. Yay.

------
cwmma
Timeline of learning JavaScript

1\. Constructer's are great it's just like language x

2\. uncanny valley of realizing it's not actually like language x

3\. understanding constructors, use them everywhere

4\. get burned by subtler points of this in async functions and forgetting
new, decide to go all functional all the time

5\. have enough experience to avoid the foot guns, use constructors all the
time as they tend to be the fastest method and have the best support.

This article is at stage 4

~~~
regularfry
6\. Be Douglas Crockford.
[http://www.youtube.com/watch?v=bo36MrBfTk4&t=19m](http://www.youtube.com/watch?v=bo36MrBfTk4&t=19m)

I believe he has _some_ experience of JS.

~~~
insin
Argument From Cranky Authority (Whose Lawn You Are On)

~~~
regularfry
Possibly, but it does rather blow a hole in the argument that only people with
limited experience in JS would treat `new` as a footgun.

------
aikah
Here is the problem with Javascript.

Basically there is so many different ways to create objects that the only
thing that matters is to actually document any piece of code.

Dont use constructors if you want.But somewhere you'll have to write "new
FileReader" in the browser or "new XMLHttpRequest" because that's how an api
you are consuming works!!!

Learn how javascript constructors and prototypes work,because you just CANT
ignore them,wether you want it or not.

Truth is everybody wants to see what they wants to see in javascript.Some want
to write pure Java like OOP,some think it looks like Haskell enough to try to
write Haskell in Javascript. Javascript is no Java nor Haskell,one cant ignore
one part of Javascript just because it looks "ugly" or whatever. Javascript is
going to get classes and python like features and meta features like proxies.
Javascript doesnt fit one paradigm, and never did.

------
skywhopper
0\. Language X dominates development, but rigidly enforced design patterns and
other universal conventions make the code confusing, hard to learn, hard to
refactor, and generally slow to respond to new requirements.

1\. New language Y pops up, thrilling small-scale devs, early adopters, and
inexperienced hotshots with faster, cleaner ways of getting their jobs done
without having to deal with all the cruft of old language X.

2\. Language Y gains mindshare, inexperienced hotshots start running into age-
old problems and reinvent a few wheels.

3\. Language Y achieves dominance over the zeitgeist. Experienced software
engineers start learning it. They see all the places where design patterns and
rigid conventions could solve the potential problems they see, having run into
it all before. They proselytize how these improvements will ensure high
quality code and save all kinds of time in the future. These new patterns
become standard and adoption of Language Y grows, even in larger corporate
environments.

4\. Language Y dominates development, but rigidly enforced design patterns and
other universal conventions make the code confusing, hard to learn, hard to
refactor, and generally slow to respond to new requirements.

5\. Language Z pops up...

------
_greim_
Here's a counter-argument.

    
    
        var x = new Foo()
    

...is almost universally recognizable, and leaves little guesswork about the
intent and meaning of the code. There's a lot more ambiguity encountering
this:

    
    
        var x = foo()
    

What am I getting back? A primitive value? An instance? A singleton? I have to
go peruse the docs. `new` can definitely be abused to do non-intuitive things,
but it's still a powerful signal to future readers of the code.

~~~
mattdesl
Name your factory "createFoo", problem solved. :)

------
rogual
I stopped using constructors (and prototypes) a couple of years ago and it's
improved my relationship with JS tremendously.

A couple more benefits:

1\. You never need to see "this" again. You can refer to a method as
object.method, and when you call that reference, you're calling the method on
that object, just like in, say, Python. No "apply" madness needed.

2\. If you decide your object might take some time to construct, you can
change your "makeObject" function to be asynchronous (using promises or Node-
style callbacks). With a constructor you just can't do this.

I've come to think of the constructor/prototype system as one of those bits
that was bolted on to the rather clean "base" language of JS to meet
Netscape's demand for a "java-like" language. You can really do without it.

~~~
mckoss
It sounds like you're explicitly adding function properties to every object.
This is slow and wasteful or memory. In Python, method lookup scans the
__class__ of the object to find the method function. Python also automatically
binds the object instance to the first (self) parameter.

What you're describing does not bear much resemblance to Python.

~~~
rogual
This is true, but I believe that in modern JS implementations, the performance
difference isn't as large as one might expect.

The similarity to Python is limited to syntax — I just wanted to raise the
point that in both Python and prototype-free JS,
higherOrderFunction(object.method) does what it looks like it will do.

------
kieranajp
I've lost track of everything we're meant to have stopped using in JS by now

~~~
talmand
I tend to ignore them and continue doing what works for my needs for the
project at hand. I know sooner or later my coding style will be the "correct"
one again.

------
mattdesl
I wouldn't say constructors are the problem -- the problem is with the "new"
keyword.

I tend to use constructors like this: [https://github.com/mattdesl/module-
best-practices/blob/maste...](https://github.com/mattdesl/module-best-
practices/blob/master/README.md#constructor-best-practices)

Which leads to clear debugging (named constructors and their prototypes
showing in console) and also works well in the off chance that you need to use
"inherits" (eg on node EventEmitter).

Regarding case; it comes down to preference. I tend to name my factories
CamelCase or createCamelCase, so that the return value "camelCase" is clearly
an instance.

~~~
jbeja
Indeed, New-Agnostic Constructor Pattern, is the simpliest patter if you want
to avoid the new keyword:

    
    
       function User (name, lastname) {
           if (!(this instanceof User)) {
           return new User(name, lastname);
          }
           this.name = name || 'Unknown';
           this.lastname = lastname || 'Unknown'
       };

~~~
phpnode
note that this pattern will break subclassing:

    
    
        var Person = User.extend({});
    
        var person = Person();
        person instanceof Person; // false!
        person instanceof User; // true

~~~
insin
The pattern didn't break subclassing there, your code did by not continuing
the pattern and then not using new :)

Personally, I only use this pattern for cases where it's more convenient not
to have to use new (e.g. building declarative APIs for defining things) and
let 'use strict'; catch the rest.

~~~
phpnode
this part here is supposed to solve the problem with people forgetting new:

    
    
        if (!(this instanceof User)) {
           return new User(name, lastname);
        }
    

I'm pointing out that this doesn't work if you extend the class.

The point is - don't forget `new` because tricks like this will not save you,
in fact this is arguably worse - you think you're getting a `Person` but you
get a `User` with no immediate errors, at least if you forget `new` then
you'll get an error straight away in strict mode.

~~~
rizalp
I've using Js for quite some time, and the behavior of prototype chain and
instanceof always give me headache when I'm trying to do simple inheritance...

For now, I'll keep using `_.create` to do Inheritance. Of course it means
another library to keep using and more verbose. But whatever...

    
    
        var Person = function(){ User.call(this) };
    
        Person.prototype = _.create(User.prototype, { 'constructor': Person });
    
        var p = new Person();
    
        p instanceof User //true
        p instanceof Person //true

------
VeejayRampay
The curse of Javascript:

1) Someone explains how using modern techniques can make for more maintainable
code with less coupling and more reusability.

2) Someone pops in and notes that "Feature X/Y/Z is not available for browsers
A, B, C"

In the end, people will keep on using the old constructors because they work
all the time everywhere. And this is bad because this article does make a
whole lot of sense.

I often have the very same problem when I look at
[https://developer.mozilla.org/en/docs/Web/JavaScript/Referen...](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype)
or [https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Refe...](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype) where lots
of the most interesting functions of said prototypes are marked as
"experimental" and most likely won't be universally available before 2016 or
so.

~~~
couchand
The article describes a way to avoid the use of 'new' entirely, but you can
just as easily get the advantages of factory encapsulation without the use of
Object.create.

    
    
        var MyModule = (function() {
    
            function OneImplementation() {}
            function OtherImplementation() {}
    
            function factoryMethod() {
                if (foobar) {
                    return new OneImplementation();
                }
                else {
                    return new OtherImplementation();
                }
            }
    
            return {
                create: factoryMethod
            };
        })();
    

As long as the use of new doesn't leak out of the module you're getting all of
the advantages. Upgrade to Object.create when you get the chance, but don't
let that hold you back.

------
drderidder
Crockford has good recommendations on when to use `new`, or not, in his 2006
post on the topic[1]. I like most of what the author says re. classical OO in
JS, but would stop short of not using `new` at all. Its a long-established
standard and the open/close principle[2] is probably not enough of a concern
in most applications to warrant using a different / slower / sometimes
unsupported method. And there are functional programming libraries for
extending objects[3]. Just encourage people to use idiomatic JS and then layer
on solutions when and if they become a problem.

The article uses stories of obscure bugs as justification. These stories get
used an awful lot to justify dogma on everything from strict typing to
Promises to whatever. I feel that's misguided - there will always be enough
rope to hang oneself with in any language, and those errors should have been
mitigated by diligent use of static code analysis (linting) and unit testing.
The author's book _Programming JavaScript Applications_ [4] (which looks
excellent otherwise) doesn't cover testing, either, but devotes a chapter to
using _logging_ for debugging. I'd rather advocate using lint-on-save, test-
driven development, test coverage, and continual integration.

Also, for a deep dive into OO criticism, Thomas Neimann's article _Nuts to
OOP!_ is a must-read. [5]

[1] [http://yuiblog.com/blog/2006/11/13/javascript-we-hardly-
new-...](http://yuiblog.com/blog/2006/11/13/javascript-we-hardly-new-ya/)

[2]
[http://en.wikipedia.org/wiki/Open/closed_principle](http://en.wikipedia.org/wiki/Open/closed_principle)

[3] [http://underscorejs.org/#extend](http://underscorejs.org/#extend)

[4]
[http://shop.oreilly.com/product/0636920033141.do](http://shop.oreilly.com/product/0636920033141.do)

[5] [http://www.embedded.com/design/prototyping-and-
development/4...](http://www.embedded.com/design/prototyping-and-
development/4216597/Nuts-to-OOP)

~~~
regularfry
Douglas Crockford's been making this argument this year at conferences:
[http://www.youtube.com/watch?v=bo36MrBfTk4&t=19m](http://www.youtube.com/watch?v=bo36MrBfTk4&t=19m)
(linked to the `new` bit, but the whole thing's worth watching).

> These stories get used an awful lot to justify dogma on everything from
> strict typing to Promises to whatever. I feel that's misguided - there will
> always be enough rope to hang oneself with in any language, and those errors
> should have been mitigated by diligent use of static code analysis (linting)
> and unit testing.

Paraphrasing the talk I just linked to, it's always better to have a language
which will guide you away from writing the bug in the first place than to have
to come back with a linter and fix it up.

------
vgallur
Another interesting point of view about constructors:

[http://www.2ality.com/2013/07/defending-
constructors.html](http://www.2ality.com/2013/07/defending-constructors.html)

~~~
shangxiao
Awesome, bookmarked like it's 1999.

Seriously though the snippet for the forgetting-new protection in a
constructor seems quite handy. It's always good to hear arguments from both
sides of the fence.

------
cphoover
I use style X of coding so your style is wrong!!! God this needs to stop.

------
gibbitz
The biggest reason for using "new" in my practice is to keep the value of the
"this" keyword on the instance within the function scope. Ihave to agree with
the other commenters here. We all know JavaScript isn't OO. I just wish OO
programers would stop trying to force their concepts and patterns on it. It
makes maintenance a nightmare for those who didn't write it and didn't code
Java/C#/Lisp or whatever OO language their concept originated in before
picking up JavaScript.

------
benaston
This article is so wrong I don't know where to start. Sorry.

------
okhudeira
Note: this is from 2012-09-17 -- title should be updated.

~~~
outdooricon
done

------
projectileboy
It makes me so glad to see that the Javascript community will spend the next
decade making all of the same stupid mistakes of useless overdesign that were
made by the Java community (and probably others). Tangentially, what is it
about the software community that makes us waste time with new and different -
but not necessarily better - implementation technologies? Is this common in
other fields?

~~~
afarrell
Because the primary figure of merit for software is "understandability by
other engineers", which is impossible to test objectively.

------
samselikoff
Anybody else find that text shadow on the headings unbearable?

