了解高阶 JavaScript 函数

Understanding higher order JavaScript functions

我正在从 Eloquent JavaScript 学习高阶函数,我研究了一个类似的问题,但找不到它。在同一主题和同一章中有一个与我相关的类似问题,但这是一个基本问题。 这是类似的 link: Higher-order functions in Javascript.

我遇到了以下代码的问题:

function repeat(n, action) {
  for (let i = 0; i < n; i++) {
    action(i);
  }
}

let unless = (test, then) => {
  if(!test)then();
};

repeat(3, n => {
  unless(n%2 == 1, () => {
    console.log(`${n} is even`);
  });
});

// Output:
/  → 0 is even
// → 2 is even
  1. 这个高阶函数是如何工作的?
  2. 循环如何确定数字是偶数还是奇数?
function repeat(n, action) {
 for (let i = 0; i < n; i++) {
   action(i);
 }
}

n 是您要执行 action 函数的次数。

这里调用的action函数是一个回调函数

如果你这样做 repeat(5, console.log) 你将拥有:

0
1
2
3
4

你也可以像这样执行另一个function

repeat(5, item => console.log(item));

一般来说,你的除非函数听起来像 - 接受条件,测试它,然后 运行 回调。 repeat func 听起来像 运行 action(s) n 次。结果听起来像运行 action(s),如果满足条件就往里面看,然后运行 unless function.

高阶函数要么接受一个函数作为参数,要么return一个函数; unlessrepeat 都接受函数作为参数。

repeat 接受一个数字和一个函数,并简单地调用传递给它的任何函数,调用该次数。

unless 接受一个值和一个函数;如果该值为 falsy,则将调用该函数。

这表明函数可以像任何其他变量一样传递:在 repeat() 中,action 指的是函数本身,而 action() 调用该函数来获取它的结果。

什么是高阶函数?

Functions that operate on other functions, either by taking them as arguments or by returning them, are called higher-order functions.

让我从一个小例子开始,然后我们回到问题中的问题。

function evenNumberFilter(number) {
  return number%2==0
}

function oddNumberFilter(number) {
  return !evenNumberFilter(number)
}

evenNumberFilter(2) // true
oddNumberFilter(3)  // true

现在我们知道是否调用函数了

  1. evenNumberFilterparameter X 它将 return true 如果它是偶数
  2. oddNumberFilterparameter X 它将 return true 如果它是奇数

我们把问题延伸一下再说

  1. "I would like to have all even numbers till number 10"
  2. "I would like to have all odd numbers till number 10"

function evenNumberFilter(number) {
  return number %2 == 0
}

function oddNumberFilter(number) {
  return !evenNumberFilter(number)
}

function evenNumberBeforeTen() {
  const result = []
  for(number=0; number<10; number++) {
    if (evenNumberFilter(number)) {
      result.push(number)
    }
  }
  return result
}

function oddNumberBeforeTen() {
  const result = []
  for(number=0; number<10; number++) {
    if (oddNumberFilter(number)) {
      result.push(number)
    }
  }
  return result
}

evenNumberBeforeTen();  //[0,2,4,6,8]
oddNumberBeforeTen();   //[1,3,5,7,9]

如果我们查看代码,evenNumberBeforeTenoddNumberBeforeTen 共享大量通用代码

  1. for循环的迭代方式
  2. 结果附加到数组的方式
  3. 在函数末尾 returned 的结果。

这两个函数之间的唯一区别是,filter 它在 evenNumberFilteroddNumberFilter 上运行。

那么我们可以重构代码并编写一个通用的 filter 函数,它可以将 谓词 作为参数吗?

Predicate: a boolean-valued function P: X? {true, false}.

In our case both evenNumberFilter and oddNumberFilter are predicates

function evenNumberFilter(number) {
  return number %2 == 0
}

function oddNumberFilter(number) {
  return !evenNumberFilter(number)
}

function filter(predicate) {
  const result = []
  for(number=0; number<10; number++) {
    if (predicate(number)) {
      result.push(number)
    }
  }
  return result
}

filter(evenNumberFilter);  //[0,2,4,6,8]
filter(oddNumberFilter);   //[1,3,5,7,9]

现在,在上面的示例中,函数 filter 是高阶函数,因为它以函数 predicate 作为参数。

让我们进入你在问题中提到的问题。

repeat是一个高阶函数,它以number和函数action作为参数。

unless是一个高阶函数,它以boolean和函数then作为参数

当你执行

repeat(3, n => {
  unless(n%2 == 1, () => {
    console.log(`${n} is even`);
  });
});
  1. repeat先被调用,然后会执行下面3次的函数。

function (n) => {
  unless(n%2 == 1, () => {
    console.log(`${n} is even`);
});

  1. 当调用上述函数时,参数为0,1,2。它使用 n%2==1 的布尔值调用 unless 函数,它将是 truefalse 并且函数下面作为参数。

function() => {
  console.log(`${n} is even`);
});

当使用 truethen 调用 unless 时,它不会执行 then 函数,因此不会打印日志

当使用 falsethen 调用 unless 时,它将执行 then 打印日志的函数