2015-10-22 38 views
2

(免責聲明:我在學習JavaScript的過程) 我有一個對象的構造函數,像這樣:使用`this`在foreach()

var Palette = function() { 
    this.colors = ["red", "green", "blue"]; 
    this.getColorCombinations = function() { 
     var combos = []; 
     this.colors.forEach(function(a) { 
      this.colors.forEach(function(b) { 
       if(a !== b) { 
        combos.push([a, b]); 
       } 
      }); 
     }); 
     return combos; 
    }; 
} 

var p = new Palette(); 
alert(JSON.stringify(p.getColorCombinations())); 

與預期輸出:

[["red","green"],["red","blue"],["green","red"],["green","blue"],["blue","red"],["blue","green"]]

經過一番研究之後,我意識到這不起作用,因爲在內部匿名函數中,「this」指向全局對象,而不再指向Palette實例。

我的問題是,處理這個問題的「JavaScript方式」是什麼?我發現應用,綁定,調用或簡單地將this分配給一個變量可以解決類似的問題,但到目前爲止,我還沒有找到任何關於內部匿名函數中引用this始終如一的最佳實踐的示例。

here是JsFiddle。 (我把它修改爲輸出到更容易的文本複製一個div)

+0

取決於你是否transpile支持舊的瀏覽器。最好的解決方案是胖箭頭功能: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions 第二好的是羅西百科的答案。任何專業的開發人員都可能熟悉它們。 –

+0

...第三好的是'Function.prototype.bind'。 – eush77

回答

5

this作爲第二個參數forEach

arr.forEach(callback, thisArg); 

MDN Documentation

thisArg
可選。在執行回調時使用此值。

我已經updated your fiddle顯示它的用法,但要點是改變這一呼籲:

this.colors.forEach(function(a) { 
    this.colors.forEach(function(b) { 
     if(a !== b) { 
      combos.push([a, b]); 
     } 
    }); 
}); 

要這樣:

this.colors.forEach(function(a) { 
    this.colors.forEach(function(b) { 
     if(a !== b) { 
      combos.push([a, b]); 
     } 
    }); 
}, this); // <- pass this as second arg 

值得注意的還有是很多其他Array.prototype中的方法接受回調也支持這個成語,包括:

  • forEach
  • map
  • every
  • some
  • filter

但是,如果你只需要指定什麼this勢必調用函數時,並且函數集作爲對象的財產,那麼最常用的方式可能是Function.prototype.call()Function.prototype.apply()

如果ES6是提供給你,然後一個箭頭的功能就更好了,因爲它繼承this從調用上下文:

this.colors.forEach(a => { 
    this.colors.forEach(b => { 
     if(a !== b) { 
      combos.push([a, b]); 
     } 
    }); 
});