title: es6基础知识3(函数拓展)
tags:
- 参数默认值
- 剩余参数
- 箭头函数
categories:
- 前端
1. 函数参数默认值
es6中关于函数的拓展主要有函数参数默认值
、rest剩余函数
、箭头函数
。函数的拓展是es6中比较重要的一部分内容。
es6之前,如果要设定函数的参数的默认值,需要通过编码来实现,也就是通过或符号||
来实现,例如var x = x || 100
, 这样就设置了x的默认值为100。
function func1(x, y) {
// 通过||符号设置函数参数默认值,x为100,y为200
var x = x || 100;
var y = y || 200;
}
这种方法非常不直观,有了es6之后,可以将函数参数的默认值写在形参后面,更加方便:
function func2(x = 100, y = 200) {
...
}
只是需要注意的是,这种写法最好将带有默认值的形参只能写在参数列表的最后面,也就是当函数有多个参数,而只有部分参数具有默认值时,这些参数只能写在参数列表的最后面:
function func3(a, b, c = 100) {
// 这里a,b没有默认值,而c有一个默认值,所以把c写在最后面
}
这样做的原因主要是避免调用函数时可能产生的错误:
// 加入将带有默认参数的形参写在前面
function func4(c = 100, b, a) {
}
// 如果在调用函数的时候想使用c的默认值,不在第一参数位传参,这样写就会报错
func4( , 200, 100)// 报错
2. 剩余参数
假设有一种情况,我们想写一个求和函数来计算输入的任意多个参数的和,比如sum(0, 1, 2, 3) = 6
, sum(0, 1, 2, 3, 4, 5) = 15
。在es6之前,如果要实现这个功能,需要用到函数中的arguments对象。
function sum() {
let args = arguments; // 这里利用arguments对象拿到函数的实参,因此函数的形参没有意义,也就可以不用写
let ret = 0;
for (let i = 0; i < args.length; i++) {
ret = ret + args[i];
}
return ret
}
console.log(sum(1, 2, 4, 4)); // 11
虽然利用arguments对象可以解决任意多个参数这种问题,但毕竟显得不太直观,有了es6以后,这个问题就简单多了,我们可以使用剩余参数很方便的来解决这个问题。剩余参数的写法是在函数定义时在形参前面加上...
符号,仍然用刚才的那个例子来说明:
function sumes6(...newNumber){
let ret = 0;
for(let i = 0; i < newNumber.length; i++) {
ret = ret + newNumber[i];
}
return ret;
}
console.log(sumes6(1, 2, 4, 4)); // 11
剩余参数可以理解为把函数输入的实参源源不断的压入到函数的形参newNumber中,需要指出的是,这里可以采用数组的方法来访问到每一个传入的参数,但是newNumber实际上是一个对象而不是一个数组。
3. 箭头函数
箭头函数是es6中新增的一种简单的函数表达式写法。
// 习惯的函数定义方式
function func1(x, y) {
}
// 箭头函数写法
let func1 = (x, y) => {}
箭头函数具有很多方便的特点,第一个是当箭头函数的参数有且只有一个的时候,箭头函数参数的()
可以省略:
// 有这样一个箭头函数
let func1 = (x) => {
return x + 1;
}
// 这个箭头函数的参数只有一个所以可以省略参数可括号()
let func1 = x => {
return x + 1;
}
// 注意省略括号的情况是箭头函数的参数有且只有一个,所以当函数没有参数时,括号也不可以省略
let func2 = () => {
return 100;
}
第二个特点就是如果箭头函数的语句有且只有一条,那么{}
也可以省略,并且这条语句如果是返回语句return
,那么return
也可以省略。
let func1 = (x) => {
return x + 1;
}
// 上面这样一个函数就可以简写为
let func1 = x => x + 1;// 这种情况下,语句执行的结果就是返回值
需要注意的是,如果这唯一的一条语句返回的是一个字面量对象,那么箭头函数的{}
依然不可以省略
let func1 = () => {
return {
x: 100,
y: 200
}
}// 这种情况下函数体的括号是不可省略的,也就是不可以书写成下面的形式
let func1 = () => {
x: 100,
y: 200
}//这样的写法是错误的
箭头函数的另一个特点是,箭头函数内部的this
在函数的创建期就完成了绑定。this
的绑定就像js
玄幻小说,简直是让人琢磨不透,对于大部分的普通函数,他们的this
在执行期绑定,下面这样一个栗子:
<!DOCTYPE html>
<html lang="en">
<head>
<title>箭头函数</title>
</head>
<body>
<button>按钮一</button>
<button>按钮二</button>
<script>
function changeColor () {
this.style.color = 'red';// 在函数定义的时候并不知道this指向谁
}
let btns = document.querySelectorAll('button')
for(let i = 0; i < btns.length; i++) {
btns[i].onclick = changeColor
}
</script>
</body>
</html>
上面这个例子中给两个按钮都绑定了同一个事件函数changeColor
,函数在创建的时候并没有确定this
指向谁,只有当用户点击了按钮,确定了点用changeColor
的对象时,才能明确this
的指向,所以这样一个粒子的效果就是用户点击那一个按钮,那个按钮就改变颜色。
接下来利用箭头函数重写上面的那个粒子:
<!DOCTYPE html>
<html lang="en">
<head>
<title>箭头函数</title>
</head>
<body>
<button>按钮一</button>
<button>按钮二</button>
<script>
// function changeColor () {
// this.style.color = 'red';
// }
let changeColor = () => {
this.style.color = 'red'
}
let btns = document.querySelectorAll('button')
for(let i = 0; i < btns.length; i++) {
btns[i].onclick = changeColor
}
</script>
</body>
</html>
然后在浏览器中执行,发现这一次并没有实现点击按钮,按钮改变颜色的功能,并且函数还爆出了错误箭头函数.html:16 Uncaught TypeError: Cannot set property 'color' of undefinedat HTMLButtonElement.changeColor
,这个时候在控制台中打印出this
发现此时this
指向的是window
对象。