【问题标题】:Higher order functions - Javascript高阶函数 - Javascript
【发布时间】:2023-03-21 19:04:01
【问题描述】:

我正在使用 Eloquent Javascript。 count 函数接受一个数组和一个测试函数 (equals(x)) 作为参数,并返回数组中测试函数返回 true 的元素数量。

我了解这些函数的工作方式,并且逻辑上传递给 reduce 的匿名函数的 total 参数的值为零。

有人可以帮我看看总价值的具体来源吗?我想在脑海中有一个更清晰的画面。

function count(test, array) {
  return reduce(function(total, element) { // Where is the value for total coming from?
    return total + (test(element) ? 1 : 0);
  }, 0, array);
}

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

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

之前的减少函数:

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

之前的forEach函数:

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

【问题讨论】:

  • base 被作为 total 参数传递,据我所知。 base 这里是 0,所以 total 在那个评估中是 0。
  • 是的,逻辑上我可以看到。我只是不清楚价值的具体来源。
  • 这似乎与您的last question 几乎相同。这与您的上一个问题有什么不同?
  • 是的,今天早上我又把昨天的东西都抽出来了,很清楚。这是它之后的以下代码。我想我只是在努力查看使用函数作为参数时行的运行方式。
  • 所以看起来,是的,否则你当然不会问这个问题:P 我认为最好,如果你在我们开始之前描述你的思路,函数是如何交互的关于回答这个问题。

标签: javascript higher-order-functions


【解决方案1】:

我看到 reduce 被传递一个匿名函数而不是组合函数

这不是真的。匿名函数combine 函数。

combine(base, element)function(total, element)

这两个函数调用本质上是相等的:combine(base,element) 和 function(total,element)?

不,它们是完全不同的东西。

前一个函数调用,指向combine引用的函数。
然而,第二个计算为一个新的函数值。在这种情况下:

reduce(function(total, element) {...}, ...);

reduce() 正在被传递一个函数值,这意味着 新函数创建,一个接受两个参数的函数(由 @987654327 表示@ 和 element)。然后将此函数传递给reduce


让我从昨天开始回收我的可视化。重要的是要意识到,这不仅适用于你的情况,而且适用于reduce(left)概念的每个实施例.

                   return value of reduce()
                   /
                 etc ...
                /
            combine    
           /       \
       combine      xs[2]
      /       \
  combine      xs[1]
 /       \
0         xs[0]

当然,这只显示发生了什么,而不是如何,我认为在你的情况下,你要求如何。只要记住这个可视化,看看结果会怎样。

替换函数

为了更清楚地说明发生了什么,我将逐步替换正在传递的函数。

程序开始:

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

equals(0)(你可以称之为柯里化的一种形式)计算为一个函数,该函数被传递给count()

这基本上会产生以下count() 函数:

function count(array) {
  return reduce(function(total, element) { // Where is the value for total coming from?
    return total + (0 == element ? 1 : 0);
  }, 0, array);
}

从这里,我们可以提取combine 参数:

function combine(total, element) { // Where is the value for total coming from?
    return total + (0 == element ? 1 : 0);
}

这是在reduce函数中使用的函数:

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

reduce(0, array) 是从 count() 函数调用的。考虑到combine 的帐户实现,现在可以像这样重写传递给forEach 的函数:

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

请记住,base 代表我们的total

作为我们的最后一步,我们会考虑 forEach() 的作用。

function reduce(base = 0, array) {
  for (var i = 0; i < array.length; i++)
    base = base + (0 == array[i] ? 1 : 0);
  }
  return base;
}

这就是count() 本质上的样子,所有调用都未包装:

function count(array) {
  var base = 0;
  for (var i = 0; i < array.length; i++)
    base = base + (0 == array[i] ? 1 : 0);
  }
  return base;
}

【讨论】:

    【解决方案2】:

    您传递给 reduce 的 3 个参数是:

    {
        combine:function(total, element){...},
        base:0,
        array:array
    }
    

    然后该函数接受base 并将其作为total 参数传递给combine 函数:

    base = combine(base, element);
    

    基本上,这里发生的情况是,对于您刚刚传递的数组中的每个元素(作为第三个参数 array),该函数接受参数 base 并使用您提供的匿名函数递增它(首先检查元素是否通过test)。最后,在遍历完所有元素后,返回最终值base

    也许这有助于解释:

    function count(test, testarray) {
      var anon = function(total, element) { // Where is the value for total coming from?
        return total + (test(element) ? 1 : 0);
      };
      //now anon is a function.
      return reduce(anon, 0, testarray);
    }
    

    让我们仔细看看函数调用和定义:

    return   reduce(anon   , 0   , testarray);
                      |      |     |
                      v      v     v
    function reduce(combine, base, array) {
        combine;    //the function that is passed in as the first argument
        base;       //the number that is passed in as the second argument
        array;      //the array that is passed in as the third argument
    

    anon0testarray 中的每一个的 被传递到函数中。在函数内部,它们的值可以通过函数定义中的参数名称来访问。

    【讨论】:

    • 这就是我的假设。感谢您的验证。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-09
    • 1970-01-01
    • 2017-09-06
    • 2016-05-07
    相关资源
    最近更新 更多