【问题标题】:Javascript High Order FunctionsJavascript 高阶函数
【发布时间】:2025-04-28 13:00:02
【问题描述】:

我是函数式编程的新手,我很难理解以下函数中实际发生的事情。

const someFnc = arg => arg("You can print that string :)");
someFnc(msg => console.log(msg))

据我所知,我实际上将一个函数传递给了函数 someFnc。但是如何将函数 arg 作为 arg(...) 进行自我调用(在我的示例中,使用字符串的参数)? 我真的对这个概念感到困惑。

【问题讨论】:

  • arg 不是自调用的。调用在someFncarg("You can print that string :)"))的函数体中。
  • 我不确定您所说的“自我调用”是什么意思。 someFnc 调用函数arg,它在执行时声明为参数。

标签: javascript function lambda


【解决方案1】:

如果你把它拆开,你可以看到发生了什么:

function someFunction(fn) {
    fn('hello')
}

function logFunction(msg) {
    console.log(msg)
}

someFunction(logFunction)

基本上,someFunction 接受一个参数 (fn),它应该是一个函数。

然后它传递一个字符串 ("hello") 作为该函数 (fn('hello')) 的参数。

someFunction 然后执行它收到的函数,所以它正在执行logFunction('hello')

logFunction 接受一个字符串参数并在控制台记录它 (console.log('hello'))

箭头函数 ((arg) =>) 是编写 function(arg) { } 的简写。

【讨论】:

    【解决方案2】:
    const someFnc = arg => arg("You can print that string :)");
    

    只是匿名的制作方式:

    function someFnc (arg) {
      arg("You can print that string :)");
    }
    

    你定义的另一个匿名函数:

    msg => console.log(msg)
    

    这会产生一个匿名函数,它接受msg 并将其用于对console.log 的调用。因为它只是用第一个参数调用console.log,所以它是一个什么都不做的包装器。您确实可以将其替换为 console.log:

    someFnc(console.log)
    

    现在使用替换规则,我们可以用函数体替换函数调用,并将参数替换为绑定变量,因此:

    arg("You can print that string :)");        // replace arg with console.log
    // ===
    console.log("You can print that string :)");
    

    现在,当您在 JavaScript 中编写裸字时,例如 parseInt,它是一个变量。它评估为一个函数。因此parseInt("10"); // ==> 10。在你的函数体中arg 是一个变量,它获取对象console 上属性log 的值。它是一个类似于parseInt 的函数。变量是值,函数也是值。

    当您将值传递给 as 函数时,它会绑定到其定义中的变量。它甚至可以隐藏现有功能:

    ((parseInt, value) => parseInt(value))(Number, "10"); 
    // => 10
    

    所以规则是用参数替换绑定的变量,因此它真的是:​​

    Numer("10"); //=> 10
    

    变量只是值的名称。函数是一个值,您可以将 () 放在后面以应用,可选地在其中包含参数。

    【讨论】:

    • “只是匿名方式” — 从 ES 2015 开始,上述 sn-p 中的函数将具有 inferred function name someFnc
    • @Xufox 是的,这是真的。解析器从最近的绑定中修饰函数对象使调试变得更加容易,但是分配的表达式会生成一个匿名函数。 IMO ((fun=>fun.name)(()=>1)) 也可以返回 fun,但它没有。
    • 难道不是 msg => console.log(msg) 一个 lambda 函数而不是一个包装器吗?
    • 两者兼有。 lambda 通常是匿名函数的名称,msg => console.log(msg) 都是一个 lambda,它可以在您的代码中替换 console.log 而无需更改功能。第二个它没有改变任何东西,它是一个包装器。