使用filter()检查碰撞?

时间:2016-06-19 10:00:47

标签: javascript filter collision-detection

通常我在解决JS中的问题时没有太多麻烦,但这次我真的需要帮助理解这段代码。 Mary Rose Cook在她的太空入侵者游戏中使用了这个逻辑来过滤body数组以找到与其他身体的碰撞。

var bodies = [];
...
update: function () {
// bodies is an array of all bodies in the game
var bodies = this.bodies;
var notCollidingWithAnything = function (b1) {
    return bodies.filter(function(b2) { return colliding(b1, b2); }).length === 0;
};

this.bodies = this.bodies.filter(notCollidingWithAnything)

// ...insert function to draw the bodies that are in the new bodies array...

}

有人可以解释一下this.bodies.filter(notCollidingWIthAnything)如何工作而不将任何参数传递给参数函数?编译器如何知道检查数组的每个元素是否与数组的每个其他元素相对应?请引导我了解编译器中究竟发生了什么,以便我能理解这一点。

1 个答案:

答案 0 :(得分:3)

  

有人可以解释this.bodies.filter(notCollidingWIthAnything)如何工作而不将任何参数传递给参数函数吗?编译器如何知道检查数组的每个元素与数组的每个其他元素?

编译器(以及JavaScript引擎)知道如何使用元素调用notCollidingWIthAnything; Array#filter确实如此。

notCollidingWIthAnything是对该函数的引用。 (函数是JavaScript中的正确对象,因此我们引用它们就像我们引用其他对象一样。)代码将该引用传递给Array#filter,然后Array#filter调用每个元素执行一次函数在数组中,传入元素值(以及索引和数组;它传递三个args,尽管我们通常只使用第一个)。然后它使用回调的返回值来决定是否将元素包含在它构建的新数组中。

这是Array#filter简化代码,因此您可以看到正在发生的事情:

function arrayFilter(callback) {
    // Remember this is called with `this` referring to an array-like object

    // Create a new, empty array for the result
    var result = [];

    // Loop through the items
    for (var index = 0; index < this.length; ++index) {
        // Get the value for this entry
        var value = this[index];

        // Call the callback
        if (callback(value, index, this)) {
            // Got a truthy return value, include the value in the result
            result.push(value);
        }
    }

    // Return the new array
    return result;
}

再次,那是简化,不完全正确;有关完美正确的步骤,请参阅the algorithm in the spec

这是一个日志记录显示究竟是谁在做什么的例子:

function arrayFilter(callback) {
  console.log("Starting arrayFilter");
  var result = [];
  for (var index = 0; index < this.length; ++index) {
    var value = this[index];
    console.log("arrayFilter calling callback with value " + value);
    if (callback(value, index, this)) {
      console.log("arrayFilter got truthy result, include the value");
      result.push(value);
    } else {
      console.log("arrayFilter got falsy result, don't include the value");
    }
  }
  console.log("arrayFilter done");
  return result;
}

function isOdd(value) {
  var retval = value % 2 == 1;
  console.log("isOdd called with " + value + ", returning " + retval);
  return retval;
}

var a = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log("calling `arrayFilter` with `a` as `this`, using `isOdd` callback");
var odds = arrayFilter.call(a, isOdd);

console.log("Resulting array: ", odds);