2021.04.26(rest参数、尾调用)

rest 参数

ES6 引入 rest 参数(形式为 ...变量名  ),用于获取函数的多余参数,这样就不需要使
用 arguments  对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。

1.  function add(...values) {
2.  let sum = 0;
3.
4.  for (var val of values) {
5.  sum += val;
6.  }
7.
8.  return sum;
9.  }
10.
11.  add(2, 5, 3) // 10

上面代码的 add  函数是一个求和函数,利用 rest 参数,可以向该函数传入任意数目的参数。

下面是一个 rest 参数代替 arguments  变量的例子。

1.  // arguments变量的写法
2.  function sortNumbers() {
3.  return Array.prototype.slice.call(arguments).sort();
4.  }
5.
6.  // rest参数的写法
7.  const sortNumbers = (...numbers) => numbers.sort();

上面代码的两种写法,比较后可以发现,rest 参数的写法更自然也更简洁。

注意,rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。

1.  // 报错
2.  function f(a, ...b, c) {
3.  // ...
4.  }

函数的 length  属性,不包括 rest 参数。

1.  (function(a) {}).length // 1
2.  (function(...a) {}).length // 0
3.  (function(a, ...b) {}).length // 1

尾调用优化

尾调用(Tail Call)是函数式编程的一个重要概念,本身非常简单,一句话就能说清楚,就是指某个
函数的最后一步是调用另一个函数。

1.  function f(x){
2.  return g(x);
3.  }

上面代码中,函数 f  的最后一步是调用函数 g  ,这就叫尾调用。

以下三种情况,都不属于尾调用。

1.  // 情况一
2.  function f(x){
3.  let y = g(x);
4.  return y;
5.  }
6.
7.  // 情况二
8.  function f(x){
9.  return g(x) + 1;
10.  }
11.
12.  // 情况三
13.  function f(x){
14.  g(x);
15.  }

上面代码中,情况一是调用函数 g  之后,还有赋值操作,所以不属于尾调用,即使语义完全一样。情
况二也属于调用后还有操作,即使写在一行内。情况三等同于下面的代码。

1.  function f(x) {
2.  if (x > 0) {
3.  return m(x)
4.  }
5.  return n(x);
6.  }

上面代码中,函数 m  和 n  都属于尾调用,因为它们都是函数 f  的最后一步操作。

尾调用优化

这就叫做“尾调用优化”(Tail call optimization),即只保留内层函数的调用帧。如果所有函数
都是尾调用,那么完全可以做到每次执行时,调用帧只有一项,这将大大节省内存。这就是“尾调用优
化”的意义。

注意,只有不再用到外层函数的内部变量,内层函数的调用帧才会取代外层函数的调用帧,否则就无法
进行“尾调用优化”。

注意,目前只有 Safari 浏览器支持尾调用优化,Chrome 和 Firefox 都不支持。

 

2021-04-26 11:23:24

posted @ 2021-04-26 14:03  铁打的代码流水的bug  阅读(98)  评论(0)    收藏  举报