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.