Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
258 views
in Technique[技术] by (71.8m points)

Simulate the 'new' operator in JavaScript

I tried to simulate the 'new' operator in JavaScript in a code like this:

Function.method('new', function ( ) {
    var objPrototype = Object.create(this.prototype);
    var instance = this.apply(objPrototype, arguments);

    return instance;
});

However, in order to cover all the cases, the return statement should look like this:

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

Now for the tests:

var SomeClass = function (param1, param2) {
    this.param1 = param1;
    this.param2 = param2;
};

var test1 = String.new('test1'); //in this case, the "instance" variable is an object
var test2 = SomeClass.new('test1', 'test2'); // in this case, the "instance" variable is undefined

Is this exactly what the 'new' operator does? Is there any case left to cover?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...