The answers here are all valid for standard ES5, which was all there when when they were written, but they are not general solutions that will work in all ES6 contexts, so I want to expand on them. The short answer is that the code from the question:
Function.method('new', function ( ) {
var objPrototype = Object.create(this.prototype);
var instance = this.apply(objPrototype, arguments);
return instance;
});
would in a standard ES6 environment be better implemented as
Function.method('new', function ( ) {
return Reflect.construct(this, arguments);
});
which definitely simplifies things.
Reflect.construct
was introduced in ES6 as part of the Proxy
system, but it has general uses like this situation.
The reason this is the preferred method now is the simple reason that .apply
doesn't work on every type of function anymore. The previous answer explains that new
calls the internal language function [[Construct]]
to initialize the argument. The approach using .apply
essentially replaces the automatic object-creation and calling logic handled in [[Construct]]
by instead manually creating the object and then calling the function, which uses it's [[Call]]
internal method instead of [[Construct]]
.
The call to the function is part of what changed in ES6. In ES5 pretty much the only thing you'll be constructing is a normal function Foo(){}
value, so you can make assumptions about that. In ES6, class Foo {}
syntax was introduced, and the constructor functions created by class syntax have more restrictions in place, so the assumptions made about ES5 do not apply. Most importantly, ES6 classes are explicitly disallowed from using [[Call]]
. Doing the following will throw an exception:
class Foo {}
Foo();
This is the same issue as .call
and .apply
. They are not function-constructing functions, they are function-calling functions. So if you try to use them on an ES6 class, they will throw exceptions.
Reflect.construct
avoids these issues by actually calling [[Construct]]
and not [[Call]]
, but exposing it via an API that can be used without new
.