ES6函数拓展
ES6参数默认值的设置
ES5中设置参数默认值的写法
function animal(name, type) {
var name = name || 'yuan';
var type = type || 'monkey';
console.log(name, type);
}
这个写法有个缺陷:参数传递进来的布尔值必须为true,如果传入的值为空字符串或者undefined 等这些转换为false的参数,则会影响结构。所以,ES6为了弥补这个缺陷,做了如下设置:
function animal(name = 'yuan', type = 'monkey') {
console.log(name, type);
}
触发默认值
声明函数时,可以为任意参数指定默认值,在已指定默认值的参数后可以继续声明无默认值参数
function makeRequest(url, timeout = 2000, callback) {
console.log(url);
console.log(timeout);
console.log(callback);
}
在这种情况下,只有当不为第二个参数传入值或主动为第二个参数传入undefined时才会使用timeout的默认值
rest 参数
// 求和,把结果赋值给 result
function sum(result, ...values) {
console.log(values); // [1, 2, 3, 4],这个变量返回的是一个数组
values.forEach( function(value, index) {
result += value;
})
console.log(result);
}
sum(11, 1, 2, 3, 4,); // 21
如上,rest参数(3个点 + 变量名)表示的是:获取函数多余的参数,且这个变量是一个数组。还有一点要注意的是rest参数必须是尾参数,后面不能加其他的参数,否则会报错:
// 错误写法
function sum(res, ...values, another) {
console.log(values);
}
sum(); // 报错:Uncaught SyntaxError: Rest parameter must be last formal parameter
name属性
ES6中增加了函数的name属性
const animal = function() {};
animal.name; // "animal"
Function 构造函数会发的函数实例,name 属性的值为“anonymous”
(new Function).name; // "anonymous"
bind 返回的函数,name属性值会加上“bound”前缀
function animal() {};
animal.bind({}).name; // "bound animal"
匿名函数的bind 返回的值“bound”
(function () {}).bind({}).name; // "bound"
箭头函数
1、定义
用箭头“=>”来定义函数。
2、用法
对比
// ES5 写法
var sum = function(a) {
return a;
}
// ES6 写法
var sum = a => a;
如上代码,在ES6中,第一个a表示函数参数,箭头“=>”后面的 a 表示函数体。
上述只是针对一个参数和函数体只有一条语句的写法,若函数参数的个数和函数体的语句超过1个要如何表示呢?如下:
var sum = (a, b) => { return a + b};
sum(1,4); // 5
如上,若函数的参数个数超过一个时,需要用圆括号“()”来代表参数,函数体的语句条数超过一条时,需要用大括号将它们括起来。
当函数体中返回的是对象时,我们需要将其用圆括号“()”括起来:
var person = name => ({ name: 'yuan', type: 'monkey'});
尾递归
函数调用自身叫做递归,如果尾调用自身就是尾递归。
function factorial(n) {
if(n === 1) return 1;
return n * factorial(n - 1);
}
factorial(5); // 120
在ES6 中只要使用尾递归,就不会发生栈溢出,相对节省内存。
尾递归改写
为了确保最后一步只调用自身,需要对尾递归函数进行改写,把所有用到的内部变量改写成函数的参数。
使用柯里化函数编程思想,将多参数的函数转换成单参数的形式:
function curring(fn, n) {
return function (m) {
return fn.call(this, m, n);
}
}
function tailFactorial(n, total) {
if(n === 1) return total;
return tailFactorial(n - 1, n * total);
}
const factorial = curring(tailFactorial, 1);
factorial(5); // 120
采用ES6的函数默认值改写:
function factorial(n, total = 1) {
if(n === 1) return total;
return factorial(n - 1, n * total);
}
factorial(5); // 120
在尾调用优化时,循环是可以用递归代替的,而一旦使用递归,就最好使用尾递归。