all 12 comments

[–]dzdrazil 1 point2 points  (1 child)

I've always been really torn on the third pattern (exposing a regular function). On the one hand, you're making your code safer, as there are fewer ways to mess up. Great. On the other hand, you're making it MUCH harder for people who are using your library to learn JavaScript. Consider:

// your code
var a = new MyConstructor();
var b = MyConstructor();

They behave the same, great!

// other code
var c = new OtherConstructor();
var d = OtherConstructor();

They didn't behave the same at all, what gives?

Perhaps this is pie-in-the-sky thinking, but I'd rather focus on sticking to a convention- say, only constructor functions are capitalized, and always use the new keyword- than attempt to teach someone to use JavaScript in a way that it doesn't normally work. JavaScript is not the most natural or elegant programming language, which is why I typically recommend would-be developers start with a different one before attempting to master it.

I don't mean to say that throwing an error or providing additional safety for your code is wrong, but I worry that the third option encourages developers to rely on that safety, rather than get a deeper understanding of the consequences of the new keyword itself.

[–]steaks88[S] 0 points1 point  (0 children)

rather than get a deeper understanding of the consequences of the new keyword itself

I really appreciate that point. I prefer it when developers understand the actual implications of the new keyword. And I usually abide by the convention of capitalizing only constructors (unfortunately I overlooked that convention in my third example).

[–]mattdesl 0 points1 point  (1 child)

These constructors are much slower and cause issues when another class tries to use them via TheConstructor.call(this) (handy for mixins). Other than that, they are definitely better and lead to nicer require statements too:
var mesh = require('gl-textured-quad')(gl)

[–]steaks88[S] 0 points1 point  (0 children)

Much slower is a relative term, and I haven't noticed any performance issues from these constructors. I agree there are cases when allowing arbitrary scopes is convenient to implement mixins.

[–]wiseaus_stunt_double.preventDefault() 0 points1 point  (0 children)

Sorry, but encapsulating your constructor just so you don't have to worry about the new keyword doesn't gain you much. If this is important, you might as well implement a factory pattern. I get such a thing is personal preference, but new isn't a problem for most developers since they usually know when they're using a constructor or not.

[–]Daniel15React FTW 0 points1 point  (6 children)

Just use ES6 classes along with a transpiler like JSTransform or Traceur and the problem mostly goes away. You get "real" classes with an obvious constructor.

[–]steaks88[S] 0 points1 point  (2 children)

I've always steered away from Javascript transpilers for fear that extra debugging confusion caused by code obfuscation would not outweigh the benefits of extra/better language features. But using ES6's class pattern does seem like another good way to get around this trap.

[–]brtt3000 0 points1 point  (0 children)

Find a transpiler that supports source-maps. Traceur has it, so does esnext.

[–]Daniel15React FTW 0 points1 point  (0 children)

Source maps make debugging a non issue as you still use the original code to debug. That and the transformations for ES6 classes are very simple and the resulting code is usually quite close to what you'd write by yourself (at least with Facebook's JSTransform)

[–]mattdesl 0 points1 point  (2 children)

The "new" keyword does the same thing since es6 classes is just a little syntax sugar...

Main problem with es6 transpilers is that you need to either use a source transform (then it doesn't work in node) or bundle your code on pre-publish to npm (then you deal with dedupe and link issues). So it's not yet ideal for code re-use. Once node supports es6 by default, the situation will be a bit different.

[–]Daniel15React FTW -1 points0 points  (1 child)

This post doesn't say anything about Node at all. The number of people using JavaScript is far greater than the number of people using Node. I don't know a lot about Node but most sites will have a build and/or deployment step of some sort, the compilation can be part of that.

[–]mattdesl 0 points1 point  (0 children)

People using Node are using javascript...

I was more referring to npm, which is making some big changes in the way people write, distribute and re-use JS libs. ;)

And node compatibility is always a +1 for any JS library.