如何在嵌套的forEach中访问外部调用者

时间:2016-12-31 00:05:26

标签: javascript arrays foreach

我从MDN学习this。 有一个功能循环'

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的另一种用法,如下所示。我希望this中的collisionDetect()引用b中的来电者loop()

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

非常感谢你。

3 个答案:

答案 0 :(得分:2)

您可以将局部变量绑定到@IBAction func unwindToHomeController(segue: UIStoryboardSegue) { self.performSegue(withIdentifier: "toPerson", sender: self) }

this

另一种方法是使用ES6箭头函数,因为它们保留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) +")"; } } }); }

this

答案 1 :(得分:1)

这是Array#forEach的签名:

arr.forEach(callback[, thisArg])

正如您所看到的,Array#forEach接受第二个参数thisArgs,它在执行回调时设置this

因此,将当前this作为第二个参数传递,它将被分配给回调:

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
}

答案 2 :(得分: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));
}