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

浙公网安备 33010602011771号