本文共 3833 字,大约阅读时间需要 12 分钟。
The production NewExpression : new NewExpression is evaluated as follows:
- Evaluate NewExpression.
- Call GetValue(Result(1)).
- If Type(Result(2)) is not Object, throw a TypeError exception.
- If Result(2) does not implement the internal method, throw a TypeError exception.
- Call the [[Construct]] method on Result(2), providing no arguments (that is, an empty list of arguments).
- Return Result(5).
回到上述定义,其大意是,new 后必须跟一个对象并且此对象必须有一个名为 [[Construct]] 的内部方法(其实这种对象就是构造器),否则会抛出异常,比如:
var Str = "test";var aStr = new Str;// FF 显示“Str is not a constructor”// IE 显示“对象不支持此操作”var Num = new Number(999);var aNum = new Num;// 结果同上
如果符合以上条件,那么引擎将调用其 [[Construct]] 内部方法,并不提供入口参数。接下来便要考察此内部方法。
另外,下面一段是 new 运算符的带参用法,由于和无参用法区别不大,读者朋友可直接略过。
The production MemberExpression : new MemberExpression Arguments is evaluated as follows:
- Evaluate MemberExpression.
- Call GetValue(Result(1)).
- Evaluate Arguments, producing an internal list of argument values (11.2.4).
- If Type(Result(2)) is not Object, throw a TypeError exception.
- If Result(2) does not implement the internal [[Construct]] method, throw a TypeError exception.
- Call the [[Construct]] method on Result(2), providing the list Result(3) as the argument values.
- Return Result(6).
When the [[Construct]] property for a Function object F is called, the following steps are taken:
- Create a new native ECMAScript object.
- Set the property of Result(1) to “Object”.
- Get the value of the prototype property of the F.
- If Result(3) is an object, set the property of Result(1) to Result(3).
- If Result(3) is not an object, set the [[Prototype]] property of Result(1) to the original Object prototype object as described in 15.2.3.1.
- Invoke the property of F, providing Result(1) as the this value and providing the argument list passed into [[Construct]] as the argument values.
- If Type(Result(6)) is Object then return Result(6).
- Return Result(1).
根据这些内容,我们完全可以构造一个伪 [[Construct]] 方法来模拟此流程(其实已有众多前辈做过此工作):
function MyObject(age) { this.age = age;}MyObject.construct = function() { var o = {}, Constructor = MyObject; o.__proto__ = Constructor.prototype; // FF 支持用户引用内部属性 [[Prototype]] Constructor.apply(o, arguments); return o;};var obj1 = new MyObject(10);var obj2 = MyObject.construct(10);alert(obj2 instanceof MyObject);// true
PROPERTY | DESCRIPTION |
---|---|
[[CONSTRUCT]] | Constructs an object. Invoked via the new operator. Objects that implement this internal method are called constructors. |
[[CLASS]] | A string value indicating the kind of this object. |
[[CALL]] | Executes code associated with the object. Invoked via a function call expression. Objects that implement this internal method are called functions. |
[[PROTOTYPE]] | The prototype of this object. |