Simulate the ‘new’ operator in JavaScript

From the specification:

11.2.2 The new Operator #

The production NewExpression : new NewExpression is evaluated as follows:

  1. Let ref be the result of evaluating NewExpression.
  2. Let constructor be GetValue(ref).
  3. If Type(constructor) is not Object, throw a TypeError exception.
  4. If constructor does not implement the [[Construct]] internal method, throw a TypeError exception.
  5. Return the result of calling the [[Construct]] internal method on constructor, providing no arguments (that is, an empty list of arguments).

The production MemberExpression : new MemberExpression Arguments
is evaluated as follows:

  1. Let ref be the result of evaluating MemberExpression.
  2. Let constructor be GetValue(ref).
  3. Let argList be the result of evaluating Arguments, producing an internal list of argument values (11.2.4).
  4. If Type(constructor) is not Object, throw a TypeError exception.
  5. If constructor does not implement the [[Construct]] internal method, throw a TypeError exception.
  6. Return the result of calling the [[Construct]] internal method on constructor, providing the list argList as the argument values.

In either case, all steps are correctly followed:

var objPrototype = Object.create(this.prototype);    // 1-4 1-5
var instance = this.apply(objPrototype, arguments);  // 5   6

The point of interest is 2.
The specification for [[construct]] states:

When the [[Construct]] internal method for a Function object F is
called with a possibly empty list of arguments, the following steps
are taken:

  • Let obj be a newly created native ECMAScript object.
    . . .
  • Let result be the result of calling the [[Call]] internal property of F, providing obj as the this value and providing the argument list
    passed into [[Construct]] as args.
  • If Type(result) is Object then return result.
  • Return obj.

typeof obj returns "object" for null, while null is not an object. However, since null is a falsy value, your code also works as intended:

return (typeof instance === 'object' && instance ) || objPrototype;

Leave a Comment