表达式评估 - 为什么括号会改变"这个"参考?

时间:2015-04-30 10:51:25

标签: javascript

考虑示例模块创建,为什么括号会更改this引用?

正如section 11.2.2 in JavaScript specification所说:

  

生产NewExpression:新的NewExpression被评估为   如下:

     
      
  1. 让ref成为评估NewExpression的结果。
  2.   
  3. 让构造函数为GetValue(ref)。
  4.   
  5. 如果Type(构造函数)不是Object,则抛出 TypeError 异常。
  6.   
  7. 如果构造函数没有实现[[Construct]]   内部方法,抛出 TypeError 异常。
  8.   
  9. 返回结果   在构造函数上调用[[Construct]]内部方法,不提供   参数(即一个空的参数列表)。
  10.   

经过一些调查后,之间没有差异(有吗?):

console.log(new (modules.getModule('foo')).method)
console.log(new (modules.getModule('foo')).method())

两个样本method都已执行。

更有趣:

console.log(typeof new modules.getModule('foo').method) // function
console.log(typeof new (modules.getModule('foo')).method) // object

这些差异的根源是什么?



var modules = (function() {
    var definitions = {
        foo: {
            method: function() {
                this.thing = 'baz';
            }
        }
    };
    
    return {
        getModule: function(name) {
            if(name in definitions) {
                return definitions[name];
            }
        }
    };
}());


alert('this: ' + new modules.getModule('foo').method()) // undefined
alert('this: ' + new (modules.getModule('foo')).method()) // {this.thing = 'baz'}




2 个答案:

答案 0 :(得分:4)

括号不会更改方法调用的this引用。括号会更改NewExpression评估的new

如果new运算符位于属性链(表达式后跟访问器)的前面,它将评估链并实例化结果构造函数。

如果new运算符位于调用表达式(表达式,可能包括访问器,后跟参数列表)之前,则调用将提供new操作的参数。任何尾随访问器都将访问新实例化对象的属性。

对于您的示例,这意味着

 new  modules.getModule ('foo') .method
 new  modules.getModule ('foo') .method()
// are evaluated as
(new (modules.getModule)('foo'))…
// on which then .method is accessed or called

new  (modules.getModule('foo')).method
new  (modules.getModule('foo')).method ()
// are evaluated as
new ((     …                  ).method)() // the empty parentheses are optional for `new`

(modules.getModule('foo')).method
// just evaluates to the `method` function
(modules.getModule('foo').method)

答案 1 :(得分:0)

变量模块获取匿名函数返回的值:带有getModule方法的对象。

在第一种情况下:

console.log(new (modules.getModule('foo')).method)

new 应用于对象 foo 的函数方法(这是 modules.getModule('foo')的结果)。控制台应显示功能方法。 在第二种情况下:

console.log(new (modules.getModule('foo')).method())

现在, new 应用于对象 foo (这是 modules.getModule('foo')的结果。 foo 有一个方法方法。 但是这一次,方法被执行了。控制台应显示具有 baz 属性的对象。

console.log(typeof new modules.getModule('foo').method) // function

在这里,您询问对象 foo 的方法方法的类型( modules.getModule('foo')的结果)。 显然,这种类型是一种功能。

console.log(typeof (modules.getModule('foo')).method) // object

在这里,您要求方法的类型 method ,它是对象 foo 的一部分(这是 modules.getModule('foo)的结果“)