简体   繁体   English

雄辩的JavaScript,第二版,第5章高阶函数

[英]Eloquent JavaScript, 2nd Edition, Chapter 5 Higher-Order Functions

I'm very new to JavaScript, and I was hoping to get some help with Chapter 5 in the 2nd Ed. 我是JavaScript的新手,我希望在第二版的第5章中获得一些帮助。 of Eloquent JavaScript. 雄辩的JavaScript。 Specifically, I ran into the example below: 具体来说,我遇到了以下示例:

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

I think I understand the concept of higher-order functions producing other functions, but I'm not sure I understand the idea of "capturing" and how it pertains here. 我想我理解生成其他函数的高阶函数的概念,但是不确定我是否理解“捕获”的概念以及它在这里的含义。 Specifically, the line with var val = f(arg); 具体来说, var val = f(arg); .

Can someone please walk me through that line of code? 有人可以引导我浏览该行代码吗? How do you pass an argument to another argument? 您如何将一个参数传递给另一个参数? I'm not sure if I'm using the correct terminology, so please excuse me if I've got it wrong. 我不确定我是否使用了正确的术语,所以如果我记错了,请原谅。 I just don't understand that line and couldn't easily find any other threads about this subject. 我只是不明白那条线,无法轻易找到与此主题相关的其他主题。

Thanks! 谢谢!

noisy is a function that takes a reference to another function f and returns a new function that wraps f so that it's call and return values are logged to the console. noisy是一个函数,它引用另一个函数f并返回一个包装f的新函数,以便将其调用和返回值记录到控制台。

val is the result of the function f being called, where f is a function reference that is passed when noisy is called. val是调用函数f的结果,其中f是调用noisy时传递的函数引用。

To go step by step: 要逐步进行:

// noisy accepts argument f (where f itself appears to be a function)
function noisy(f) {
    // noisy returns a new function that takes an argument arg
    return function(arg) {
        // when this new function is called, it logs to console
        console.log("calling with", arg);
        // the function you originally passed to noisy is now called, with the return value stored in val
        var val = f(arg);
        // return value val also logged to console
        console.log("called with", arg, "- got", val);
        // return value val is returned from the generated function
        return val;
    };
}
// noisy is called with the inbuilt function Boolean and the argument 0 (to test the boolean value of 0)
noisy(Boolean)(0);

Another use case could be something like this: 另一个用例可能是这样的:

function someFuncToMonitor(someArg) {
    return someArg + 1;
}
monitoredFunc = noisy(someFuncToMonitor);
result = monitoredFunc(5);
// calling with 5
// calling with 5 - got 6

So in short calling monitoredFunc calls your someFuncToMonitor function for you and tells you about the call and the results. 因此,在短期呼叫monitoredFunc调用你的someFuncToMonitor功能为你,并告诉你关于呼叫和结果。

Code in question: 有问题的代码:

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

What happens (kind of like a "magic schoolbus" journey through JavaScript): 发生了什么(类似于通过JavaScript进行的“神奇的校车”之旅):

  1. Nothing is actually executed until the line of code noisy(Boolean)(0); 直到代码行noisy(Boolean)(0);才实际执行任何操作noisy(Boolean)(0);
  2. When this line is reached, first the noisy function is called with the JavaScript built-in function Boolean as its argument f . 到达此行时,首先使用JavaScript内置函数Boolean作为其参数f调用noisy函数。
  3. An anonymous function is returned: 返回一个匿名函数:
    • when run, the anonymous function receives a new argument called arg . 运行时,匿名函数会收到一个称为arg的新参数。
    • then the anonymous function will log the string "calling with" followed by the arg . 然后匿名函数将记录字符串“ calling with”,后跟arg
    • then the anonymous function will call the function f (which has been memoized within the anonymous function by closure) and store the return value in the variable val . 然后匿名函数将调用函数f (已通过闭包在匿名函数中进行了记忆)并将返回值存储在变量val
    • then the anonymous function will log the string "called with" followed by arg , followed by the string "- got", followed by val . 然后匿名函数将记录字符串“ with with”,后跟arg ,后跟字符串“ -get”,后跟val
    • finally, the anonymous function will also return the value in the variable val . 最后,匿名函数还将返回变量val的值。
  4. The return value of noisy(Boolean) is the anonymous function as described above, with Boolean playing the role of f within this anonymous function that was just generated. 如上所述, noisy(Boolean)的返回值是匿名函数, Boolean在刚刚生成的该匿名函数中扮演f的角色。
  5. The remaining (0) is now used to call this newly generated anonymous function with an argument arg of 0. 剩余的(0)现在用于以参数arg 0调用此新生成的匿名函数。
  6. The five sub-steps described in 3. above are followed, resulting in: 遵循上面3.中描述的五个子步骤,结果是:
    • no visible output, but arg takes on a value of 0 as the initial step of the anonymous function's invocation. 没有可见的输出,但是arg的值为0作为匿名函数调用的第一步。
    • the anonymous function logs the string "calling with 0" 匿名函数记录字符串“用0呼叫”
    • the Boolean function is run with an argument of 0, which returns false , which is stored into val . Boolean函数使用参数0运行,该参数返回false ,并将其存储到val
    • the anonymous function logs the string "called with 0 - got false" 匿名函数记录字符串“用0调用-得到假”
    • the anonymous function returns false (but this value is not used or stored in any way by the example code). 匿名函数返回false (但是示例代码未以任何方式使用或存储此值)。

Now let's go through the actual lines of code and match them with the above steps: 现在,让我们看一下实际的代码行,并将其与上述步骤匹配:

  1. This code begins to be executed: noisy(Boolean) 此代码开始执行: noisy(Boolean)
  2. The following code within noisy is executed, with argument Boolean being passed into noisy and stored into the variable f : 执行noisy的以下代码,将Boolean参数传递给noisy并存储到变量f

     return function(arg) { console.log("calling with", arg); var val = f(arg); console.log("called with", arg, "- got", val); return val; }; 
  3. The noisy(Boolean) part of this code noisy(Boolean)(0); 此代码的noisy(Boolean)部分noisy(Boolean)(0); has now been replaced with the return value shown in step 2. 现在已替换为步骤2中显示的返回值。
  4. So now the line noisy(Boolean)(0) has in effect become [[anonymous function]](0) . 因此,现在noisy(Boolean)(0)实际上已成为[[anonymous function]](0)
  5. This replacement "code" [[anonymous function]](0) is now executed. 现在执行此替换“代码” [[anonymous function]](0)
  6. As a result, the following lines of code are executed: 结果,将执行以下代码行:

      console.log("calling with", 0); // because 0 was passed in for arg var val = Boolean(0); // because Boolean is stored in f console.log("called with", 0, "- got", false); // because the Boolean value of 0 is false 

The noisy function takes a single parameter f which is a function. 噪声函数采用单个参数f ,该参数为函数。 When you call noisy, it returns a new function (which means noisy(Boolean) returns a function). 当您调用noisy时,它将返回一个新函数(这意味着noisy(Boolean)返回一个函数)。 The capturing takes place because the new function has access to any parameters of noisy, including the f parameter (programmers call this concept a closure). 之所以进行捕获是因为新函数可以访问任何嘈杂的参数,包括f参数(程序员将此概念称为闭包)。 When you have noisy(Boolean)(1) the f inside the inner function is referring to Boolean . 当您有noisy(Boolean)(1) ,内部函数中的f引用Boolean So, val gets set to Boolean(1) since var val = f(arg) . 因此,由于var val = f(arg) ,所以val设置为Boolean(1) var val = f(arg)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM