简体   繁体   English

有人可以解释这个高阶 JavaScript 函数令人困惑的语法吗?

[英]Can someone explain this higher-order JavaScript function confusing syntax?

I am reading the book "Eloquent JavaScript".我正在阅读“Eloquent JavaScript”这本书。

In Chapter 5 he describes a particular higher-order function.在第 5 章中,他描述了一个特定的高阶函数。 It is called noisy() it is printed below...它被称为noisy()它打印在下面......

function noisy(f) {
  return (...args) => {
   console.log("calling with", args);
   let result = f(...args);
   console.log("called with", args, ", returned", result);
   return result;
 };
}

Here is the part that is confusing me.这是让我困惑的部分。 He calls the function noisy as follows...他调用函数noisy如下...

noisy(Math.min)(3,2,1);

I do not understand why the function is called that way.我不明白为什么以这种方式调用该函数。 Why isn't it called like this...为什么不叫这个...

noisy(Math.Min(3,2,1))

Edit: I see now what is going on.编辑:我现在明白发生了什么。 It was explained by Simone below.下面由 Simone 解释。

noisy(Math.min)(3,2,1) is equivalent to (noisy(Math.min))(3,2,1).

If you try to get the type of noisy , you'll get:如果您尝试获得noisy类型,您将获得:

typeof noisy
>> "function"

Same thing if you ask for the type of noisy(Math.min) :如果您要求noisy(Math.min)类型noisy(Math.min)同样的事情:

typeof noisy(Math.min)
>> "function"

If you want you can also store this function into a variable:如果需要,您还可以将此函数存储到变量中:

const noisyFunction = noisy(Math.min)

So that you can call it like a regular function:这样你就可以像普通函数一样调用它:

noisyFunction(1,2,3)

noisy(Math.min)(3,2,1) is exactly the same, just written in a different, shorter way. noisy(Math.min)(3,2,1)完全相同,只是以不同的、更短的方式编写。 The main point is, a higher-order function is just a function that returns a function.重点是,高阶函数只是一个返回函数的函数。

noisy takes a function as a parameter, and returns a function. noisy将函数作为参数,并返回一个函数。 The thing you pass it is expected to be a function.你传递的东西应该是一个函数。 We can see that in this line here:我们可以在这里看到这一行:

let result = f(...args);

f is the parameter. f是参数。 That line of code using it as a function.将其用作函数的那行代码。

noisy gives you a function back. noisy给你一个功能回来。 We can see that here in the code:我们可以在代码中看到:

return (...args) => {返回(...参数)=> {

The important thing is that a function is not the same as the value returned by a call to the function.重要的是,函数与调用函数返回的值不同。 Math.min is a function, a thing. Math.min是一个函数,一个东西。 Math.min(1, 2, 3) is a call to a function , an action -- which returns a number. Math.min(1, 2, 3)对函数调用,是一个动作——它返回一个数字。 When you put the parentheses on Math.min , that tells the compiler you want to execute Math.min .当您将括号放在Math.min ,它告诉编译器您要执行Math.min

Math.min(1, 2, 3) doesn't return a function, it returns a number. Math.min(1, 2, 3)不返回函数,它返回一个数字。 The code you were given isn't passing that parameter list to Math.min ;您给出的代码没有将该参数列表传递给Math.min it's passing that parameter list to a completely different function, the one returned by noisy .它正在将该参数列表传递给一个完全不同的函数,即由noisy返回的函数。

This becomes more clear if we assign the values to local variables:如果我们将值分配给局部变量,这将变得更加清晰:

//  x is a function, not a number. 
var x = Math.min;

//  y is a function: noisy returns a function.
var y = noisy(x);

//  Call the function noisy returned:
var z = y(1, 2, 3);

If we break down your version of the call, noisy(Math.Min(3,2,1)) , we get this:如果我们分解你的电话版本, noisy(Math.Min(3,2,1)) ,我们会得到:

//  Set x equal to the integer value 1
var x = Math.min(3, 2, 1);
var y = noisy(x);

Look inside noisy .看看里面noisy It returns a function which includes the following line:它返回一个包含以下行的函数:

let result = f(...args);

So, in your version, y is the function that noisy returns.因此,在您的版本中, ynoisy返回的函数。 It's never executed, but if it were, it would be trying to treat the integer value 1 as a function.它永远不会执行,但如果是,它会尝试将整数值1视为函数。 But an integer is not a function.但是整数不是函数。

noisy(Math.min) returns a function (see the return statement: return (...args) => { ... } ). noisy(Math.min)返回一个函数(参见 return 语句: return (...args) => { ... } )。

noisy(Math.min)(3,2,1); just immediately calls that function.只是立即调用该函数。

You could also first assign the function to a variable and then call it like this:您也可以先将函数分配给一个变量,然后像这样调用它:

let fnct = noisy(Math.min);
fnct(3,2,1);

You cannot call it like noisy(Math.Min(3,2,1)) as Math.min(3,2,1) returns a number but noisy expects a function reference to be passed (hence Math.min - note its missing the () as it's passing a reference to that function rather than the result of its execution).你不能把它像noisy(Math.Min(3,2,1))作为Math.min(3,2,1)返回一个数字,但noisy希望传递(因此函数引用Math.min -记下它的缺失()因为它正在传递对该函数的引用而不是其执行结果)。

Your call would break in line 4, ie:您的呼叫将在第 4 行中断,即:

let result = f(...args);

as f is not a function in your case but rather the result of Math.min(3,2,1) // = 1 .因为f在您的情况下不是函数,而是Math.min(3,2,1) // = 1

noisy returns a function that uses the parameter f as a callback function. noisy返回一个使用参数f作为回调函数的函数。

Here is an es5 version of the code (which needs a little more code to maintain functionality) to help you understand:下面是一个 es5 版本的代码(需要多一点代码来维护功能),以帮助您理解:

 function noisy(f) { return function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } console.log("calling with", args); var result = f.apply(void 0, args); console.log("called with", args, ", returned", result); return result; }; } //test console.log(noisy(Math.min)(3, 2, 1));

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

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