In short:
new something2() instanceof something2 === false
Relatedly, if you extend your example to use the prototype property
Something.prototype.method = function () { };
something2.prototype.method = function () { };
you will find that the prototype is not inherited in the latter case:
typeof (new Something()).method === "function"
type (new something2()).method === "undefined"
The real answer is that you are tapping into entirely different underlying machinery. Calling with new
invokes the [[Construct]] mechanism, which involves setting the [[Prototype]] property according to the .prototype
property of the constructor.
But a funny thing happens in steps 8--10 of the [[Construct]] algorithm: after setting up a new, empty object, and then attaching its [[Prototype]], it does a [[Call]] to the actual constructor, using this new empty-plus-prototype object as this
. And then, in step 9, if it turns out that that constructor returned something---it throws away that prototypally-bound, passed-as-this
object that it spent all that time setting up!
Note: you can access an object's [[Prototype]] (which is different from a constructor's .prototype
) with Object.getPrototypeOf
:
Object.getPrototypeOf(new Something()) === Something.prototype // steps 5 & 6
Object.getPrototypeOf(new something2()) === Object.prototype // default
To answer some meta-questions:
- No, don't capitalize
something2
, since it is a factory function and not a constructor. If something is capitalized, it is expected to have constructor semantics, e.g. new A() instanceof A
.
- If you're worried about the danger of clobbering the global namespace, you should start using strict mode, by putting
"use strict";
at the top of your files. One of the many nice cleanups of strict mode is that this
defaults to undefined
, not the global object, so e.g. calling a constructor without new
will result in errors the moment the constructor tries to attach properties to undefined
.
- Factory functions (aka the "closure pattern") are in general a reasonable substitute for constructors and classes, as long as you are (a) not using inheritance; (b) not constructing too many instances of that object. The latter is because, in the closure pattern, you attach a new instance of every method to every newly-created object, which is not great for memory usage. The biggest payoff, IMO, of the closure pattern is the ability to use "private" variables (which are a good thing, and don't let anyone tell you otherwise :P).