使用 forEach() 时如何将参数 'this' 绑定到数组的每个元素?

How do I bind the parameter 'this' to each element of an array when using forEach()?

语言:Javascript
操作系统:Ubuntu14.04
浏览器:在 Chromium、Chrome、Firefox 中测试。

背景

我正在制作一个 HTML5 Canvas 游戏,其中包含各种可收集的物品。这些项目的超类是 Collectable,它有一个 render() 函数:

Collectable.prototype.render = function(){
    // renders the collectables
}

Collectable有不同的子类,都将render()委托给超类。例如:

var Heart = function(x, y) {
    Collectable.call(this, x, y);
}
Heart.prototype = Object.create(Collectable.prototype);

我首先创建一个包含我所有收藏品的数组来实例化我的收藏品:

var collectables = [];
var numOfEach = 5;
// IIFE so as to not pollute global scope
(function() {
    for (var i = 0; i < numOfEach; i++) {
        // TODO: make this cleaner
        var heart = new Heart(100, 200);
        collectables.push(heart);
        var gemBlue = new GemBlue(100, 200);
        collectables.push(gemBlue);
        var gemOrange = new GemOrange(100, 200);
        collectables.push(gemOrange);
    }
})();

然后在我的游戏循环文件中,我有一个 renderEntities() 函数,它在我的 objects 上重复调用各个渲染方法:

function renderEntities() {
    // render my other objects
    ...

    // render collectables
    collectables.forEach(function() {
        // test what 'this' is bound to
        console.log(this);

        // call render method
        this.render();
    });
}

...但是在这种情况下 this 绑定到 window 因此 this.render 不是函数。

问题

如何将 this 绑定到 collectables 数组的每个单独元素?

我的研究

我已经阅读了 documentation for the bind function,但恐怕我不知道如何将其应用于 forEach() 和我的匿名函数。

然后我发现 this existing question which explained how forEach takes an optional parameter to set this. After reading the documentation on forEach 我尝试了以下但没有成功的结果:

 collectables.forEach(function() {
     // test what 'this' is bound to
     console.log(this);

     // call render method
     this.render();
 }, this);

...这显然与将 this 设置为全局 object.

具有相同的效果
 collectables.forEach(function() {
     // test what 'this' is bound to
     console.log(this);

     // call render method
     this.render();
 }, collectables);

...这让我更接近一点,因为 this 作为一个整体绑定到 collectables 数组,但显然 this.render 仍然不是一个函数。我看不到我可以在 forEach 中使用什么参数来将 this 绑定到数组的每个元素。

我觉得输入所有这些内容后答案会非常简单。我对 this 的概念比较陌生,所以请放轻松!

我还没有找到另一个问题来回答这个问题,或者至少是我能够根据我的知识水平理解的问题。例如,我考虑过以下问题:

如果我没理解错的话,您希望获得与每个收藏品相关联的 object。在这种情况下,只需为 forEach 循环传递一个参数。在这种情况下,我称该参数为 theObj,但也许 theCollectable 甚至 c 会更准确。

collectables.forEach(function(theObj) {
    // test what 'this' is bound to
    console.log(theObj);

    // call render method
    theObj.render();
});

更新: 您在 forEach 调用中传递的 this 正在将 this 的当前值传递给循环。此时,this是在window的范围内执行的,所以thiswindow。如果您不想引用 window,则不需要传递 this,并且由于 window 是全局的,所以您根本不需要传递 this,所以我已将其从建议的答案中删除。

更新: MDN 是 JavaScript 文档的重要资源:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

.forEach() 工具将三个参数传递给您的回调函数:

  1. 数组的当前元素;
  2. 数组的索引;
  3. 数组本身。

因此:

collectibles.forEach(function(collectible) {
  // the parameter "collectible" will be the
  // current array element
});

确实没有必要绑定 this,但如果您确实需要,您可以:

collectibles.forEach(function callback(collectible) {
  if (this !== collectible)
    callback.call(collectible, collectible);
  else {
    // body of function
  }
});