new A.B() 与 new A().B() 是有区别的,这个大家都知道,至于为什么,我之前一直不是很理解。
这个问题涉及到的知识面是,点运算符、new运算符、函数执行这三者之间的优先级的问题。
new A.B(); 的逻辑是这样的: | new A.B(); |
点运算符优先于new运算符,看起来似乎仅仅如此。
new A().B(); 的逻辑却是这样的: | (new A()).B(); | 而不是 | new (A().B)(); |
区别在于A后面多了一对小括号,这个影响到了优先级顺序。
ECMAScript标准里关于new运算符(11.2.2) 和function calls 的描述是下面这一段:
11.2.2ThenewOperator
The productionNewExpression:new
NewExpressionis evaluated as follows:
- Letrefbe the result of evaluatingNewExpression.
- LetconstructorbeGetValue(ref).
- IfType(constructor) is not Object, throw aTypeErrorexception.
- Ifconstructordoes not implement the [[Construct]] internal method, throw aTypeErrorexception.
- Return the result of calling the [[Construct]] internal method onconstructor, providing no arguments (that is, an empty list of arguments).
The productionMemberExpression:new
MemberExpressionArgumentsis evaluated as follows:
- Letrefbe the result of evaluatingMemberExpression.
- LetconstructorbeGetValue(ref).
- LetargListbe the result of evaluatingArguments, producing an internal list of argument values (11.2.4).
- IfType(constructor) is not Object, throw aTypeErrorexception.
- Ifconstructordoes not implement the [[Construct]] internal method, throw aTypeErrorexception.
- Return the result of calling the [[Construct]] internal method onconstructor, providing the listargListas the argument values.
11.2.3 Function Calls
The productionCallExpression:MemberExpressionArgumentsis evaluated as follows:
- Letrefbe the result of evaluatingMemberExpression.
- LetfuncbeGetValue(ref).
- LetargListbe the result of evaluatingArguments, producing an internal list of argument values (see 11.2.4).
- IfType(func) is not Object, throw aTypeErrorexception.
- IfIsCallable(func) isfalse, throw aTypeErrorexception.
- IfType(ref) isReference, then
- IfIsPropertyReference(ref) istrue, then
- LetthisValuebeGetBase(ref).
- Else, the base ofrefis anEnvironment Record
- LetthisValuebe the result of calling the ImplicitThisValue concrete method ofGetBase(ref).
- IfIsPropertyReference(ref) istrue, then
- Else,Type(ref) is notReference.
- LetthisValuebeundefined.
- Return the result of calling the [[Call]] internal method onfunc, providingthisValueas thethisvalue and providing the listargListas the argument values.
The productionCallExpression:CallExpressionArgumentsis evaluated in exactly the same manner, except that the containedCallExpressionis evaluated in step 1.
NOTEThe returned result will never be of typeReferenceiffuncis a native ECMAScript object. Whether calling a host object can return a value of typeReferenceis implementation-dependent. If a value of typeReferenceis returned, it must be a non-strict PropertyReference.
看了这么大一段逻辑,都有点怕了,不过还是看了下来,理解了一半一半。
在Javascript中,如果构造函数不带参数的话,new的时候可以省略括号。
//这两种写法是等价的
var d = new A;
var d = new A();
//但是下面这两种是不同的,不能混淆了:
var d = new A.B(); //new A.B;
var d = new A().B(); //new A().B;