2016-12-31 74 views
0

我正在學習從MDN this。 有一個函數「環」如何訪問嵌套forEach外部呼叫者

function loop(){ 
    ctx.fillStyle='rgb(255,200,124,.35)'; 
    ctx.fillRect(0,0,width,height); 

    while(balls.length<15){ 
     var ball = new Ball(); 
     balls.push(ball); 
    } 

    balls.forEach(function(b){ 
     b.draw(); 
     b.update(); 
     b.collisionDetect(); 
    }); 

    requestAnimationFrame(loop); 
} 

balls是一個數組,並且在collisionDetect()有另一種用途的forEach如下。我要讓thiscollisionDetect()指呼叫者bloop()

Ball.prototype.collisionDetect = function(){ 

    balls.forEach(function(bl){ 

     if(!(this.x===bl.x&&this.y==bl.y 
      &&this.velX===bl.velX&&this.velY===bl.velY)){ 
      var dx = this.x-bl.x; 
      var dy = this.y-bl.y; 
      var distance = Math.sqrt(dx*dx+dy*dy); 

      if(distance<this.size+bl.size){ 
       bl.color = this.color = "rbg(" 
       + random(0,255) 
       +"," 
       +random(0,255) 
       +"," 
       +random(0,255) 
       +")"; 
      } 
     } 
    }); 
} 

我試圖通過b作爲collisionDetect()參數。它確實有效,但不是預期的。

我知道兩個forEach可以簡單地換成原來的for循環,但我只是想知道我是否可以使它與forEach一起工作。

非常感謝大家。

+0

在collisionDetect函數「這個」是等於B。因此,只需在forEach之前將其捕獲到變量中,並在傳遞給forEach的函數內使用該變量即可。 – Robba

+0

我質疑本文使用的OO實踐 - 特別是'collisionDetect'。 「Ball」的一個實例不應該與封閉範圍內的任意變量「balls」有關。呸。這應該是一個「類方法」(在JavaScript的情況下,構造函數的屬性) 'Ball.collisionDetect = function(ball,balls){}' – Damon

+0

@Damon也許作者想讓代碼更容易看到和理解,因爲這是一個絕對的初學者教程:) –

回答

2

您可以將局部變量綁定到this

Ball.prototype.collisionDetect = function(){ 
    var self = this; 
    balls.forEach(function(bl){ 

     if(!(self.x===bl.x&&self.y==bl.y 
      &&self.velX===bl.velX&&self.velY===bl.velY)){ 
      var dx = self.x-bl.x; 
      var dy = self.y-bl.y; 
      var distance = Math.sqrt(dx*dx+dy*dy); 

      if(distance<self.size+bl.size){ 
       bl.color = this.color = "rgb(" + random(0,255) +"," +random(0,255) +"," +random(0,255) +")"; 
      } 
     } 
    }); 
} 

另一種方法是使用ES6箭頭函數,因爲它們保留了this

Ball.prototype.collisionDetect = function(){ 

    balls.forEach(b1 => { 

     if(!(this.x===bl.x&&this.y==bl.y 
      &&this.velX===bl.velX&&this.velY===bl.velY)){ 
      var dx = this.x-bl.x; 
      var dy = this.y-bl.y; 
      var distance = Math.sqrt(dx*dx+dy*dy); 

      if(distance<this.size+bl.size){ 
       bl.color = this.color = "rbg(" + random(0,255) +"," +random(0,255) +"," +random(0,255) +")"; 
      } 
     } 
    }); 
} 
+0

謝謝@Barmar,您的兩項建議有些工作但帶來另一個問題。 預期的結果是,當球碰撞時,它們會改變顏色並繼續移動。在我最初的試驗中,球不會因碰撞而改變顏色。你的建議確實會改變球的顏色,但球的數量也會減少,最後所有的球都會消失。你知道爲什麼嗎?如果你想看看,問題開頭的鏈接裏有一個完成的版本。謝謝。 –

+0

你可以讓一個jsfiddle來演示這個問題嗎?這裏沒有任何東西可以去除球。 – Barmar

+0

謝謝巴爾瑪。 這是你的第一個建議。 http://jsbin.com/wikijaxuze/1/edit?js,output 這是給你的第二個建議。 http://jsbin.com/luvetuzigo/edit?js,output –

0

您可以將函數綁定到您想要的任何上下文/範圍。這樣,它會工作:

Ball.prototype.collisionDetect = function(){ 

balls.forEach(function(bl){ 

    if(!(this.x===bl.x&&this.y==bl.y 
     &&this.velX===bl.velX&&this.velY===bl.velY)){ 
     var dx = this.x-bl.x; 
     var dy = this.y-bl.y; 
     var distance = Math.sqrt(dx*dx+dy*dy); 

     if(distance<this.size+bl.size){ 
      bl.color = this.color = "rbg(" 
      + random(0,255) 
      +"," 
      +random(0,255) 
      +"," 
      +random(0,255) 
      +")"; 
     } 
    } 
}.bind(this)); 
} 
+0

謝謝@abeyaz,我嘗試了你的建議,它有點作品,但也帶來了另一個意想不到的結果 在預期的結果,當球碰撞時,他們會改變顏色,並繼續前進。在我最初的試驗中,球不會因碰撞而改變顏色。你的建議確實會改變球的顏色,但球的數量也會減少,最後所有的球都會消失。你知道爲什麼嗎?如果你想看看,問題開頭的鏈接裏有一個完成的版本。謝謝。 –

1

這是Array#forEach簽名:

arr.forEach(callback[, thisArg]) 

正如你所看到的,Array#forEach接受第二PARAM,thisArgs,當它執行它設置回調this

所以,傳遞當前this作爲第二PARAM,並且將被分配到所述回調:

Ball.prototype.collisionDetect = function(){ 

    balls.forEach(function(bl){ 

     if(!(this.x===bl.x&&this.y==bl.y 
      &&this.velX===bl.velX&&this.velY===bl.velY)){ 
      var dx = this.x-bl.x; 
      var dy = this.y-bl.y; 
      var distance = Math.sqrt(dx*dx+dy*dy); 

      if(distance<this.size+bl.size){ 
       bl.color = this.color = "rbg(" 
       + random(0,255) 
       +"," 
       +random(0,255) 
       +"," 
       +random(0,255) 
       +")"; 
      } 
     } 
    }, this); // set thisArg to this 
} 
+0

謝謝@Ori Drori,我很欣賞你的建議,它有點作品但帶來另一個問題。 預期的結果是,當球碰撞時,它們會改變顏色並繼續移動。在我最初的試驗中,球不會因碰撞而改變顏色。你的建議確實會改變球的顏色,但球的數量也會減少,最後所有的球都會消失。你知道爲什麼嗎?如果你想看看,問題開頭的鏈接裏有一個完成的版本。謝謝。 –