重复的抽象

我们已经了解的普通函数就是一种很好的构建抽象的工具。但有些时候,光有函数也不一定能够解决我们的问题。

程序以给定次数执行某些操作很常见。 你可以为此写一个for循环,就像这样:

  1. for (let i = 0; i < 10; i++) {
  2. console.log(i);
  3. }

我们是否能够将“做某件事N次”抽象为函数? 编写一个调用console.log N次的函数是很容易的。

  1. function repeatLog(n) {
  2. for (let i = 0; i < n; i++) {
  3. console.log(i);
  4. }
  5. }

但如果我们想执行打印数字以外的操作该怎么办呢?我们可以使用函数来定义我们想做的事,而函数也是值,因此我们可以将期望执行的操作封装成函数,然后传递进来。

  1. function repeat(n, action) {
  2. for (let i = 0; i < n; i++) {
  3. action(i);
  4. }
  5. }
  6. repeat(3, console.log);
  7. // → 0
  8. // → 1
  9. // → 2

你不必将预定义的函数传递给repeat。 通常情况下,你希望原地创建一个函数值。

  1. let labels = [];
  2. repeat(5, i => {
  3. labels.push(`Unit ${i + 1}`);
  4. });
  5. console.log(labels);
  6. // → ["Unit 1", "Unit 2", "Unit 3", "Unit 4", "Unit 5"]

这个结构有点像for循环 - 它首先描述了这种循环,然后提供了一个主体。 但是,主体现在写为一个函数值,它被包裹在repeat调用的括号中。 这就是它必须用右小括号和右大括号闭合的原因。 在这个例子中,主体是单个小表达式,你也可以省略大括号并将循环写成单行。