ES6为函数的扩展包括:参数的默认值、rest参数、扩展运算符(…)以及箭头函数。使代码更简洁更灵活、
- 开发中,给函数的参数指定默认值,是很普遍很常见的一个需求,我们先来回顾一下传统的实现方式,对比着看更好理解:
1
2
3
4function person(n,a){
var name = n || 'Zhangsan';
var age = a || 25;
} - 上面是传统的实现方式,通过或运算实现,原理:如果运算符 || 左侧为true,直接返回左侧的值,否则返回右侧的值; 在person函数内,如果参数n没有传参,那么变量name得到的值就是“Zhangsan”,如果传参了,变量name的值就为参数n的值
- 但是,前提是参数对应的布尔值不能false(比如:数字0,空字符串等转换成布尔值就是false),这就使得这种传统的实现方式存在一定的不足和缺陷。
参数的默认值
1
2
3
4
5
6function person(name = 'Zhangsan',age = 25){
console.log(name,age);
}
person();//结果:Zhangsan 25
person('Lisi',18);//结果:Lisi 18 - 我们把默认值的设定放在了参数上:(name = ‘Zhangsan’,age = 25),这样就实现了参数name的默认值为‘Zhangsan’,age的默认值为25。而不需要在函数体内进行检测,函数体内可以专注对参数的使用或者运算,再也不用担心函数的实际传参情况了。
- 上面的案例,我们对person( )函数进行两次调用,区别是有传参数和没传参数,运行的结果也符合我们的预期:没传参,得到的是默认值Zhangsan 25,传参就会得到传入的参数值:Lisi 18。
如果函数有多个参数,但只有部分需要指定默认值,另一部分不需要的话,那么,设定默认值的参数一定要放在最后。
还有一个要注意的地方,函数的参数是默认声明的,声明过的变量,就不能用let或者const关键字再次声明,否则会报错的
1 | function person(age = 12){ |
作用域的问题(注意)
1 | //作用域需要注意的问题 |
- 如果function()括号中有变量名称 作用域始终在括号内部寻找 如果没有会对应外部的参数
rest 参数
- ES6 引入 rest 参数(形式为…变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中上面代码的add函数是一个求和函数,利用 rest 参数,可以向该函数传入任意数目的参数。
1
2
3
4
5
6
7
8
9
10
11function add(...values) {
let sum = 0;
console.log(values)// [2,5,3]
for (var val of values) {
sum += val;
}
return sum;
}
add(2, 5, 3) // 10####注意,rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。1
2
3
4
5
6
7
8function push(array, ...items) {
items.forEach(function(item) {
array.push(item);
});
}
var a = [0];
push(a, 1, 2, 3);
console.log(a)//[0,1,2,3]1
2
3
4// 报错
function f(a, ...b, c) {
// ...
}箭头函数
- ES6给我们介绍一种全新的定义函数的方式,就是用箭头符号(=>),故得名为箭头函数
1
2
3
4
5
6
7//传统写法
var sum = function(a) {
return a ;
};
//箭头函数写法
var sum = a => a; - 上面演示了两种写法,函数的作用都是一样的,传入参数a,直接返回a;第一种传统的写法大家都熟悉,我们看看第二种写法:a=>a; 这里的第一个a代表是传进去的参数,箭头=>后面的a表示函数体
- 如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分。
1
2
3
4
5
6
7
8
9var f = () => 5;
// 等同于
var f = function () { return 5 };
var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
return num1 + num2;
}; - 如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回。
1
2
3//箭头函数写法
var sum = (a,b) => {return a+b}
sum(1,2);//结果:3 - 由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错。
1
2
3
4
5// 报错
let getTempItem = id => { id: id, name: "Temp" };
// 不报错
let getTempItem = id => ({ id: id, name: "Temp" });箭头函数的this指向问题
- ES5 this指向window
1
2
3
4
5
6
7
8
9
10
11
12//定义一个对象
var obj = {
x:100, //属性x
show(){
//var _this = this
//延迟500毫秒,输出x的值
setTimeout(function(){
console.log(this.x);
},500 );
}
};
obj.show();//打印结果:undefined - 当代码执行到了setTimeout( )的时候,此时的this已经变成了window对象(setTimeout( )是window对象的方法),已经不再是obj对象了,所以我们用this.x获取的时候,获取的不是obj.x的值,而是window.x的值,再加上window上没有定义属性x,所以得到的结果就是:undefined.解决方法var _this = this 将this指向当前对象
箭头函数的this指向
1
2
3
4
5
6
7
8
9
10//定义一个对象
var obj = {
x:100, //属性x
show(){
setTimeout(
//不同处:箭头函数
() => { console.log(this.x)},500);
}
};
obj.show();//打印结果:100 - 当定义obj的show( )方法的时候,我们在箭头函数编写this.x,此时的this是指的obj,所以this.x指的是obj.x。而在show()被调用的时候,this依然指向的是被定义时候所指向的对象,也就是obj对象,故打印出:100。
箭头函数的this指向的是定义时的this对象,而不是执行时的this对象。
尾调用
- 函数的最后一句话是不是一个函数
1
2
3
4
5
6
7function tail(x){
console.log('tail',x)
}
function fx(x){
return tail(x) //fx方法的最后一句话 提升性能
}
fx(123)// tail 123