You state that:
function construct(constructor, args) {
function F() {
return constructor.apply(this, args);
}
F.prototype = constructor.prototype;
return new F();
}
should be the same as:
function construct(constructor, args) {
return new constructor.apply(this, args);
}
But it actually differs in a few fundamental ways:
1. constructor.apply
is a native non-constructor function. New
can only create objects from constructors:
[...] objects may be created [...] via constructors which create objects and then execute code that initialises all or part of them by assigning initial values to their properties. Each constructor is a function that has a property named “prototype” that is used to implement prototype-based inheritance and shared properties. Objects are created by using constructors in new expressions [...]
http://www.ecma-international.org/ecma-262/5.1/#sec-4.2.1
F
on the other hand is a function object. All function objects can be used as constructors.
Note: Alon Gubkin said new constructor.apply(this, args)
doesn't work because constructor.apply(this, args).prototype
is undefined. This is not true. If it were it would imply that the function call operator's precedence is higher than the new operator (i.e. that 'new constructor.apply(this, args) is the same as new (constructor.apply(this, args))`) which is not true.
2. Even if constructor.apply
would be a constructor function it would not be the same as constructor.prototype
. The prototype of F
is set to the constructor's
prototype to make sure all objects that are created through the new operator in combination with F
are the same as those created in combination with constructor
. The only difference between F
and constructor
being that they are different functions, thus making it possible for F
to call constructor
in a more flexible way.
constructor.apply.prototype
can actually be set to constructor.prototype
, but constructor.apply
can still not be used a constructor function.
3. In your new constructor.apply(this, args)
statement the this
argument is not pointing to the newly created object, but to the this
in local scope. So even if you could use the apply
function as a constructor with the apply's
prototype set to the constructor's
prototype you would still be passing the wrong this
to the constructor
function.
Note:
In your example
function calc()
{
function a() {return 4};
return a(); // I could easily do `return 4` instead...;
}
return
can be used with any kind of expression, while new
cannot.