3

我正在尝试从 Eloquent Javascript 一书中理解这种功能样式代码:

http://eloquentjavascript.net/chapter6.html#exercise1

当 count() 函数将匿名函数传递给 reduce() 时,代码会起作用。但是,如果我将函数分解为辅助函数,则会出现参考错误。

谁能解释为什么 count() 有效但 countHelper() 无效?

var numbers = [1,2,3,0,1,2,3,0]

function forEach(array, action) {
  for (var i = 0; i < array.length; i++)
    action(array[i]);
}

function reduce(combine, base, array) {
  forEach(array, function (element) {
    base = combine(base, element);
  });
  return base;
}

function equals(x) {
  return function(element) { return x === element;};
}

function count(test, array) {  
  return reduce(function(base, element) {
    return base + (test(element)?1:0);
  }, 0, array);
}

function countHelper(test, array) {
  function helper(base, element) {
    return base + (test(element)?1:0);
  }
  return reduce(helper(base, element), 0, array);
}

function countZeroes(array) {
  return count(equals(0), array);
}

print(countZeroes(numbers)) // 2

function countZeroesHelper(array) {
  return countHelper(equals(0), array);
}

print(countZeroesHelper(numbers)) // ReferenceError: base is not defined
4

1 回答 1

8

在中,当您将参数传递给并将其返回值传递给 reduce(这不是您想要的)countHelper()时,您实际上是在立即调用辅助函数,而不是传递对函数的引用,以便可以在需要时调用函数。你有这个:reduce()reduce()

function countHelper(test, array) {
  function helper(base, element) {
    return base + (test(element)?1:0);
  }
  return reduce(helper(base, element), 0, array);
}

应该是这样的:

function countHelper(test, array) {
  function helper(base, element) {
    return base + (test(element)?1:0);
  }
  return reduce(helper, 0, array);
}

注意reduce()函数参数的不同。

当您想将函数作为参数传递时,不要在其后包含括号,因为这只会导致它立即执行并传递执行它的返回值,而不是仅传递对函数本身的引用。

这是像 Javascript 这样的无类型语言中的一个常见错误,它允许您在任何参数中传递任何内容。即使是经验丰富的程序员也偶尔会犯这个错误(包括我自己)。要理解的重要区别是执行函数与传递对函数的引用之间的区别。

于 2013-02-15T01:23:50.813 回答