2015-04-30 55 views
3

考慮示例模塊的創建,爲什麼括號更改this參考?表達式評估 - 爲什麼括號更改「this」引用?

由於section 11.2.2 in JavaScript specification說:

生產NewExpression:

  1. 讓裁判是評估NewExpression的結果:新NewExpression爲 如下評價。
  2. 讓構造函數成爲GetValue(ref)。
  3. 如果Type(構造函數)不是Object,則拋出TypeError異常。
  4. 如果構造函數不執行[[Construct]] 內部方法,則拋出TypeError異常。
  5. 返回 的結果調用[[Construct]]內部方法的構造函數,沒有提供 參數(即參數的空列表)。

經過一番調查後,沒有差異之間(有哪些?):

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

我不知道它背後的所有技術原因,但如果它是'new modules.foo.method()'而不是'modules.getModule('foo')。method()',它不會返回undefined。它與Javascript如何確定要傳遞什麼對象以用作'this'變量有關。 'new(modules.getModule('foo')。method)()'也可以。順便說一句,我無法重現你的類型的例子。 –

+2

Mine typeof顯示爲函數 –

+0

@ShekharPankaj - 我在檢查typeof時錯過了第二個例子中的new操作符;/- updated –

回答

4

括號不改變方法調用的this參考。圓括號更改new評估的NewExpression

如果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) 
0

可變模塊獲取由所述匿名函數返回的值:用方法getModule的對象。

在第一種情況:

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

被施加到函數方法對象的FOO(這是modules.getModule( '富')的結果的。控制檯應顯示功能方法。 在第二種情況下:

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

現在,被施加到對象FOO(這是modules.getModule( '富')的結果。對象foo有一個方法方法。 但是這次執行方法。控制檯應該顯示一個物體baz

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

在這裏,你問對象FOOmodules.getModule( '富')的結果)的方法方法的類型。 該類型顯然是一種功能。

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

在這裏,你問它是對象FOO的一部分的方法方法的類型(這是modules.getModule( '富')的結果)

+0

不,'new'不適用於'modules.getModule('foo')'的結果(這可能是一個對象,而不是'* a'foo'函數*「 - 沒有這樣的函數) – Bergi

+0

你是對的:我編輯了我的答案。 –

+0

第二種解釋仍然是錯誤的。 – Bergi