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 に答える