JavaScript:Anonymous vs Helper函数

NTU*_*TUI 3 javascript functional-programming anonymous-function

我试图从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
Run Code Online (Sandbox Code Playgroud)

jfr*_*d00 8

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

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

它应该是这样的:

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

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

如果要将函数作为参数传递,则不要在其后面包含parens,因为这只会导致它立即执行并传递返回值而不是仅仅传递对函数本身的引用.

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