【问题标题】:Higher-order functions in JavascriptJavascript 中的高阶函数
【发布时间】:2014-05-08 07:23:46
【问题描述】:

我正在阅读 Eloquent JavaScript (The new edition),我到达了关于高阶函数的部分,我对以下代码中发生的事情感到困惑。

function noisy(f) {
  return function(arg) {
    console.log("calling with", arg);
    var val = f(arg);
    console.log("called with", arg, "- got", val);
    return val;
  };
}
noisy(Boolean)(0);
// → calling with 0
// → called with 0 - got false
  1. 为什么对函数的调用如此嘈杂? (Boolean) 是演员表吗?演员表干什么?返回值?还是论点?如果返回值,为什么不 (Boolean)noisy(0)。或者如果参数是被强制转换的参数,则为噪声 ((Boolean) 0)。

    noisy(Boolean)(0)
    
  2. 这一行发生了什么? f() 是在哪里定义的?

    var val = f(arg);
    

【问题讨论】:

    标签: javascript function higher-order-functions


    【解决方案1】:
    1. Boolean 是一个函数。这是您通过noisy 间接调用的函数。我知道,这有点令人困惑,因为它看起来像一个类型的名称。但在 JavaScript 中,那些最初有上限的东西(BooleanNumberString 等等)是函数。当您调用Boolean不使用 使用new)时,它会尝试将您提供的参数转换为boolean 原始值并返回结果。 (参见规范中的§15.6.1。)

    2. fnoisy 函数中的参数名称。

    JavaScript 中的函数是一流的对象。您可以将它们作为参数传递给其他函数,就像任何其他对象一样。

    当你这样做时

    noisy(Boolean)(0)
    

    发生了两件事。第一:

    // (In effect, we're not really creating a variable...)
    var x = noisy(Boolean);
    

    这给了我们一个函数,当被调用时,它将使用我们给它的参数调用Boolean,同时执行那些console.log 语句。这是您在noisy (return function(arg)...) 中看到的正在创建的函数;

    然后我们调用那个函数:

    x(0);
    

    这就是您看到控制台输出的时候。由于Boolean(0)false,您会看到Boolean 返回该值。

    这是一个更简单的例子:

    function foo(bar) {
        bar();
    }
    function testing() {
        alert("testing got called");
    }
    foo(testing);
    

    在那里,我将函数 testing 传递给 foo。我在foo 中使用的参数名称是barbar(); 行调用该函数。

    【讨论】:

    • @Crowder:但是如果那些最初有上限的东西(布尔值、数字、字符串等)是函数,为什么 var x = Number(5);警报(类型 x); // 数字;警报(x 实例函数); // 错误
    • @ShirgillAnsari:the specification 中有详细说明。 var x = Number(5)。您将函数 Number 作为函数(而不是构造函数)调用。规范says,当你这样做时,它会在必要时将其参数转换为数字(更好的例子:var x = Number("42"))。再次提醒您,您为什么希望 x 成为一个函数?
    • 哦,我明白了,既然它已经被转换成一个原始的布尔值,这就是为什么你说为什么我希望 x 是一个函数?你是这个意思吗?
    • @ShirgillAnsari: x 从来不是一个函数,也不是一个布尔值。这是号码5
    • @Crowder:哦,抱歉我犯了这个愚蠢的错误。当我也在查看您的答案(不是 cmets)时,我脑海中出现了布尔旋转。
    【解决方案2】:

    没有 () 的函数是实际函数。带有 () 的函数是对函数的调用。另请记住,JavaScript 是一种松散类型的语言,因此您无需声明变量类型。我在您的示例中添加了一些 cmets 以尝试提供帮助。

    // We define a function named noisy that takes in an argument named f. We are expecting f to be a function but this isn't enforced till the interpreter throws an error. 
    function noisy(f) {
    // Noisy returns a single item, an anonymous function. That anonymous function takes in an argument named arg
      return function(arg) {
        console.log("calling with", arg);
    // Our anonymous function then takes f (It can use f because its defined inside noisy, see closures for more details) and invokes it with the argument arg and stores the result in a variable named val. 
        var val = f(arg);
        console.log("called with", arg, "- got", val);
    // It now returns val
        return val;
      };
    }
    

    那么嘈杂(布尔)(0)就像这样工作

    f 是布尔函数

    noisy 返回这样的函数

    function(arg) {
      var val = Boolean(arg);
      return val;
    }
    

    所以现在我们有

    我们返回的函数(0)

    像平常一样执行成为

    function(0) {
      var val = Boolean(0); // false
      return val;
    }
    

    【讨论】:

      【解决方案3】:

      我对 JS 比较陌生,而且我也刚刚阅读过 Eloquent Javascript,一旦我理解了函数的调用(回答你的第 1 点),我发现它更容易理解:

      noisy(Boolean)(0);
      

      noisy(Boolean) 创建一个新函数,(0) 在它之后,因为它作为参数传递给该新函数。如果您参考大于示例:

      function greaterThan(n) {
        return function(m) { return m > n; };
      }
      var greaterThan10 = greaterThan(10);
      console.log(greaterThan10(11));
      

      也可以这样调用:

      greaterThan(10)(11);
      

      我希望这能澄清您关于为什么这样称呼它的第一个问题。

      第二个问题。 f 在:

      var val = f(arg);
      

      是在输入noisy(Boolean) 时传入noisyBoolean 函数。然后它被用作嘈杂函数中的参数。我也没有意识到 Boolean 本身可能是一个函数,而不仅仅是一种数据类型。正如其他人所说 - 它将您提供的参数转换为布尔值并返回结果。

      因此,val 变为 Boolean(arg),后者变为 Boolean(0),其计算结果为 false。如果您尝试拨打noisy(Boolean)(1);,您将看到它返回trueconsole.log("called with", arg, "- got", val); 只记录参数(在这种情况下为 0)和评估它的结果(假)。

      实际上,它已将布尔函数更改为记录参数和结果并返回结果的函数。

      我希望这会有所帮助。只是写它有助于我自己的理解。

      【讨论】:

        【解决方案4】:

        Javascript 变量没有静态数据类型。也可以为它们分配不同数据类型的变量。

        在 JS 中没有像 JAVA 等类型转换的概念。

        函数调用中的

        ()对应函数的调用。

        在这里,布尔值似乎是一个高阶函数,它作为参数传递给噪声函数。噪声函数的结果将是

        function(arg) {
          console.log("calling with", arg);
          var val = f(arg);
          console.log("called with", arg, "- got", val);
          return val;
        };

        第二个带 0 的括号用于调用此结果。

        这里,在上面的函数中,注意下面一行。

        var val = f(arg);

        这里,f 对应于之前传递的布尔函数。 arg 对应 0。

        由于返回了val,表达式的结果将是Booelan(0)的结果。

        【讨论】:

          【解决方案5】:

          如果你仍然有这个问题,我是这样理解的(它也让我很头疼..)

          function noisy(f) {
              return function(arg) {
                  console.log("calling with", arg);
                  var val = f(arg);
                  console.log("called with", arg, "- got", val);
                  return val;
              };
          }
          
          noisy(Boolean)(0)
          

          函数只是一个常规值。上一句是理解这里发生了什么的关键。

          我们的嘈杂(f)函数是一个值。这就是它返回的内容。

          noisy(f) 返回一个接受参数 (arg) 的函数。

          noisy(f) 也接受一个参数 (f)。内部函数(从函数内部调用的函数)可以访问传递给外部函数的变量和参数。

          我们正在调用我们的外部函数并将参数传递给它布尔值。我们的外部函数返回它的内部函数,它接受一个参数 (0)。 通过理解上述内容,很明显,noisy(Boolean(0)) 会简单地将参数传递给我们的外部函数, 而没有将任何东西传递给由我们的外部函数返回的内部函数。

          真的很简单。现在我们了解了它,很难相信它让我们一开始就这么头疼... */`

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-03-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-10-09
            • 1970-01-01
            • 2021-11-01
            • 1970-01-01
            相关资源
            最近更新 更多