80 comments

[ 0.26 ms ] story [ 149 ms ] thread
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... or https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... 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.

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.
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.

which part of prototype is java-like?
I think the comment author you responded to, meant that the developers behind JavaScript was "forced" to add the "new" keyword simply to make JavaScript more Java-like. Not that JavaScript actually is like Java.
The new keyword was absolutely added to be Java-like however the "prototype system" is nothing like Java.
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.

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.

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

It's not async functions, it's first class functions. Having multiple ways of calling a function doesn't compose. I have enough experience to know where the foot guns are at, but I don't like writing code that has foot guns in them. It's like `null` in Java. "Remember to check for null before using every object". "Remember to use new before every function that instantiates an object.". I'd rather programmers quit creating new classes of errors in languages for 'programmer convenience'.

Object creation has not yet caused my any performance issues, so I've not seen a reason to personally use `new`.

I'm not a JS guy, but when I read articles about Python or VIM here on HN I often want to write comments like yours. I still have a hard time accepting that after 5 the number 6 will probably be much closer to 4 again, just with more nuances.
Number 6 would probably be confidence in when it's not a performance bottleneck to not use constructors some of the time.
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.

Avoiding the use of 'new' isn't overengineering, it's idiomatic JS.
It's dogmatic not idiomatic.
JavaScript code rarely uses inheritance because it's completely out of place. Most non-trivial JS apps I've worked on make heavy use of duck-typing polymorphism. It works great because you don't need to deal with arcane class hierarchies: just make sure the object has what it needs to get its own job done.

Using a constructor in the first place in a language that really doesn't need them is what's dogmatic.

> It's dogmatic not idiomatic.

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

There are equally valid technical reasons for using `new`, so it's dogma
> 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.

damn, I've been using that word slightly incorrectly for years, and now I hate myself. Thanks.
Whoa a pleasant exchange on the internet. Yay.
What are the technical reasons to avoid using new?
How is writing a function to build an object "over-engineering"? It doesn't seem more complicated, and it appears it can help mitigate a particular human error (forgetting new).
The linter would catch the missing new
A linter to catch the bugs and then go back and fix them is more work than just making it not possible to have the bug exist. Also, the lint you are talking about is based on a typographic convention that you could easily get wrong. For instance, the linter won't catch the bug in this snippet:

``` var yourClass = require('your-class');

var myInstance = yourClass(); ```

In your example you have two "bugs", you're not capitalizing the constructor name and you're not using `new`. I would have to make two separate mistakes to reproduce the issue you're talking about.

The only way I'd make the first mistake is if I was unfamiliar with `your-class`'s API, so nothing can save me there.

JSHint would catch the second one.

Nitpick, on the nothing can save me there part. This is arguably a failure of `your-class`'s API.

A file exposing a class SHOULD either wrap it: `module.exports = function () { return new YourClass(); }` or use `if (!(this instanceof YourClass)) return new YourClass()` guards in the constructor to stop users of a class having to worry about whether or not to use new.

At least this seems to be the convention many module publishers seem to adhere to.

Yeah, but that falls under epediaman's "Stop over-engineering. YAGNI!" quote.

If you want the benefits of `new` without exposing your interface, you should totally wrap it.

But if you're going to have boilerplate like that for code that not's performance critical (and most of it is not), why not just go for Object.create() and returning the instance yourself. Less action at a distance.

Over-engineering sounds a bit of a stretch in this case. The article compares using a normal function that returns an object vs using a special function that needs to be called with different syntax and that magically returns `this`. The former doesn't seem more over-engineered to me, in fact is seems simpler than the later.
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...

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.

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'
   };
note that this pattern will break subclassing:

    var Person = User.extend({});

    var person = Person();
    person instanceof Person; // false!
    person instanceof User; // true
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.

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.

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
Works fine with npm "inherits" module. Not that you should be using instanceof anyways...
Personally, I think this makes it unclear what the code actually does--IMHO, forgetting `new` is not a real concern.

I generally just add a `create` method to the prototype so that you can do things like, `_.map(items, Constructor.create)`

The issue has very little to do with forgetting "new" and more to do with hiding implementation details and improving module composability.
This article is so wrong I don't know where to start. Sorry.
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...

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.

(comment deleted)
I use style X of coding so your style is wrong!!! God this needs to stop.
I've lost track of everything we're meant to have stopped using in JS by now
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.
"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"
`new Foo` will always outperform `Object.create(FooProto)`

If I create an interpreter that changes `new Foo` to `$new(Foo)` where $new is a JS function that uses Object.create to do what the `new` operator does in spec (e.g., treat it as syntactic sugar) then it's unlikely that `new Foo` would outperform `Object.create(FooProto)`. Just because the current interpreters are hyperfocusing on `new` doesn't mean they can't make `Object.create` faster in the future.

All requiring `new` does is add an implicit requirement that the name of your function is actually `new X` instead of `X` with the added requirement that all aliases of the function be prefixed with `new `, which is not composable.

Yeah, `new` might be faster than not using it right now, but that's a bug in the interpreters. And for a lot of objects, your inner loop is not going to be in creation.

Probably the problem with your perspective is that you're still thinking about JS "interpreters", when we don't generally have those any more - we have JITs that compile JS to machine code.

`new Foo()` is faster because it can be compiled to more efficient code today and probably always will be. Your argument is a bit like the "given a sufficiently intelligent compiler" one, I don't care about what JS engines of the future might do, I care about my code's performance today.

I find it odd that you rail against absolutes and then immediately turn around and defend your own.

If you meant that new is faster today, say so. That's not the same as "will always outperform".

I said there are few absolutes, not that there are no absolutes :)

`new Foo` has simpler semantics than `Object.create(FooProto)` and therefore I believe it will always be faster. That performance gap can of course narrow, but I think `new` will always be the fastest. Happy to be proved wrong.

> 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

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

I bet this is because most of JS compilers are optimized in lower level for certain "popular" tasks, developers use to do.
Every time I hear how using 'new is bad' (or "considered harmful") in Java or Javascript it just makes me chuckle. Refactoring is not hard with half-decent toolchain so adding extra complexity/indirection doesn't improve anything.
In most languages, I would agree with you. Unfortunately, I haven't encountered a "half-decent toolchain" in JavaScript – or at least a toolchain that would help me reliably and fearlessly refactor big bases of code.
Another point against advice like this is that you're going to be forced to use the supposedly "bad" technique when you interact with the rest of the world.

For instance, if you want to use any of Google's Javascript libraries like their map api client, you're going to be using "new". So, now you've done a bunch of work to avoid using "new" but as soon as you step outside of your bubble, you're going to have to find a way to deal with "new" anyway. So, what's the point? Just use a good linter and be done with it.

Yeah, and you also have to use Google's ugly name spacing and global scope pollution instead of modern (sane) module approaches like CommonJS.

Following an old-school technique just because you might see it in some legacy code doesn't seem like a great argument.

Perhaps he should've taken the "Constructors considered harmful" approach?
Performance isn't really a big concern unless you're creating several hundreds of thousands of new objects per second. And I would question why you need to do that in the first place...
Another interesting point of view about constructors:

http://www.2ality.com/2013/07/defending-constructors.html

  > typeof String('abc')
  'string'
  > typeof new String('abc')
  'object'
Oh dear, I think I'm getting a migraine.
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.

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?
Because the primary figure of merit for software is "understandability by other engineers", which is impossible to test objectively.
Anybody else find that text shadow on the headings unbearable?
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.
Name your factory "createFoo", problem solved. :)
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-...

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

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

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

[5] http://www.embedded.com/design/prototyping-and-development/4...

Douglas Crockford's been making this argument this year at conferences: 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.

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.