If the constructor function foo
returns an object, then new foo()
is identical to calling the function foo()
directly. We can prove this is so by examining the ECMAScript behavior for new
:
Return the result of calling the [[Construct]] internal method on constructor [i.e., the constructor function]...
The [[Construct]]
internal method of a function is a special wrapper for calling the function's [[Call]]
internal method (which is just the function's normal behavior). Let's see the end of [[Construct]]
to see how this wrapper behaves:
8) Let result be the result of calling the [[Call]] internal property of F [the function invoked by new
], providing obj as the this
value and providing the argument list passed into [[Construct]] as args.
9) If Type(result) is Object then return result.
10) Return obj.
In your case, your constructor function foo
returns an object, so step 9 of [[Construct]]
(and therefore, in turn, new foo()
) returns that object. But we see in step 10 that [[Construct]]
could return some other value called obj, which is equal to the this
value inside the constructor. Let's rewind and see what that's all about:
1) Let obj be a newly created native ECMAScript object.
...
4) Let proto be the value of calling the [[Get]] internal property of F with argument "prototype
".
5) If Type(proto) is Object, set the [[Prototype]] internal property of obj to proto.
Here we see the real power of new
: if the constructor function does not return an object (and therefore the [[Construct]]
operation launched by new
is allowed to return obj
), then prototypal inheritance takes place. The [[Prototype]]
of obj
(a.k.a. obj.__proto__
) is set to the prototype
property of the constructor method. This means that if foo
doesn't return an object (and instead modifies this
), and foo.prototype.someProp
is set, then an instance returned from var instance = new foo()
will have access to instance.someProp
.
Thus, a different way to write your code might be:
var foo = function() { };
foo.prototype.setA = function(a) { this.a = a; };
foo.prototype.setA = function(a) { console.log(this.a); };
In this case, new foo()
produces an object whose prototype chain includes foo.prototype
, while foo()
does not. This has the benefit of lower memory use: all foo
instances here share common prototypal methods, instead of having each instance carry its own separate functions.