箭头函数
基本语法
箭头函数是一种声明函数的简洁语法,它与普通函数并无本质的区别,差异性更多体现在语法格式上。
- 基本语法
//一般写法 function fn (a, b) { console.log(a, b); } //箭头函数形式 const fn = (a, b) => { console.log(a, b); }
箭头函数的基本语法有以下特点:;
- 取消了function关键字
- 以赋值符号的形式将函数赋值给函数名
- 参数与函数体之间通过箭头
=>
衔接
就目前来看,箭头函数好像没有比一般函数简单多少,甚至好像更复杂了。
这是因为箭头函数可以根据不同的函数体,参数来省略语法,而一般的函数其形式是固定的。
接下来我带大家一一讲解箭头函数的省略语法:
- 箭头函数的匿名
匿名函数在JavaScript中应用非常广泛,主要是作为回调函数,此时函数不需要函数名也可以调用。
//一般写法 function (a, b) { console.log(a, b); } //箭头函数形式 (a, b) => { console.log(a, b); }
在匿名函数中,一般的函数语法,只能将函数名fn
省略掉,而在箭头函数中,函数名是作为变量的,此时不仅仅可以省略掉函数名fn
,还可以省略掉赋值符号=
以及定义变量的关键字const/var/let
。即整体省略掉:const fn =
到此为止,箭头函数就已经非常简约了,但是箭头函数在一些情况还可以更简单。
由于JavaScript中回调函数较多,我们后续的示例都以匿名函数形式。
- 省略参数的小括号
当函数中只有一个参数,箭头函数可以省略小括号
这个语法可以省略掉参数的小括号,我们对比一下:
//一般写法 function (a) { console.log(a); } //箭头函数形式 (a) => { console.log(a); } //箭头函数缺省括号形式 a => { console.log(a); }
但是要注意,这个缺省参数的括号,只能在只有一个参数的情况下使用,哪怕没有参数也不能缺省括号。
没有参数情况:
//箭头函数没有参数 () => { console.log(123); }
- 省略大括号
当函数体内部只有一条语句,可以省略大括号。
对比:
//一般写法 function (a, b) { console.log(a, b); } //箭头函数形式 (a, b) => { console.log(a, b); } //箭头函数省略大括号形式 (a, b) => console.log(a, b);
当然这种方法仅限于函数内部只有一条语句,此处的语句就是: console.log(a, b)
。但是如果这条语句被写成:
(a, b) => { console.log(a); console.log(b); }
这样的话,由于函数内部有两条语句,大括号就不能省略。
- 省略return
上一个部分我们讲解了当函数内部只有一条语句,可以省略大括号。除此之外:
如果函数只有一条语句,且这个语句是return语句,那么可以同时省略大括号和return。
对比:
//一般写法 function (a, b) { return a + b; } //箭头函数形式 (a, b) => { return a + b; } //箭头函数省略大括号形式 (a, b) => return a + b;//这种写法是错的 //箭头函数省略大括号和return形式 (a, b) => a + b;
不过要注意(a, b) => return a + b
这个写法是错的,在箭头函数省略大括号,且这一条语句是return时,return必须被省略。
至此,我们就将箭头函数的最简洁语法展现给大家了。通过箭头函数的省略语法,在书写一些简单的函数时,可以以非常短的语句完成功能。这就是箭头函数的基本功能。
- 返回字面量表达式
在函数中,如果我们返回的数据是一个对象,且只有一条返回语句,我们看看这个情况会带来什么误解:
//不省略的箭头函数返回对象 (a, b) => { return {uname: "张三"}; } //省略大括号的箭头函数返回对象 (a, b) => return {uname: "张三"};//这种写法是错的 //省略return的箭头函数返回对象 (a, b) => {uname: "张三"};
着重看到这个语句:(a, b) => {uname: "张三"};
请问: {uname: "张三"}
的大括号是函数体的大括号,还是对象的大括号?
我们是程序的编写者,我们当然明确这个大括号属于对象,但是编译器并不能确定,这就会给编译器带来解析的错误。
所以为了避免这个错误,在使用缺省return的箭头函数返回对象时,要额外用一个小括号包起来:
(a, b) => ({uname: "张三"});
其实箭头函数和普通函数的区别也不止语法的缺省。还有一些其它的注意事项。
箭头函数的this
箭头函数的this规则
在一般的函数中,只要谁调用这个函数,那么this就是谁。
在箭头函数中,箭头函数不会创建自己的this,而是从父级继承
给一个案例帮助理解:
const btn = document.querySelector("button"); //一般函数形式 btn.addEventListener("click", function() { this.style.display = "none"; }) //箭头函数形式 btn.addEventListener("click", () => this.style.display = "none")
在上述代码中,我们用两种函数书写了代码,其功能是:点击按钮btn后,按钮消失。
- 分析第一段函数:
btn.addEventListener("click", function() { this.style.display = "none"; })
首先利用了btn
调用函数addEventListener
,然后再执行回调函数。
回调函数是被btn
调用的,所以this
就是btn
, this.style.display = "none"
语句就是把btn
给隐藏,符合要求。
- 分析第二段函数:
btn.addEventListener("click", () => this.style.display = "none")
这个函数中,回调函数是以箭头函数的形式,虽然回调函数被btn
调用,但是其this
会继承上一级的this
,即全局作用域的window
对象。那么 this.style.display = "none"
就相当于 window.style.display = "none"
,此时不仅不能完成功能,还会报错。
箭头函数不能用于构造函数
我们看一段构造函数:
function Person(name,age){ this.name = name; this.age = age; } const zhangsan = new Person("张三", 18);
由于构造函数要频繁使用this,而箭头函数没有自己的this,这就会导致其构造函数时出错。
箭头函数的换行
为了方便格式化,箭头函数提供了几种换行方法:
- 在箭头后换行
const func = (a, b, c) => 1;
- 如果省略了return,可以用小括号把返回值包起来
const func2 = (a, b, c) => ( 1 );
- 如果没有省略return,就不能省略大括号
const func3 = (a, b, c) => { return 1; };
- 将参数换行
const func4 = ( a, b, c, ) => 1;
箭头函数的参数绑定
在function定义的函数中,会存储一个argument对象,用于存储所有的参数(包括超出部分)。但是箭头函数并没有argument。所以箭头函数建议使用剩余参数来进行不定数量的参数传递。
在调用函数时,我们可能不知道用户会传几个参数进来,此时我们有两种方法解决问题,分别是动态参数与剩余参数。
动态参数
arguments
是函数内部内置的伪数组变量,它包含了调用函数时传入的所有实参。
<script> // 求生函数,计算所有参数的和 function sum() { console.log(arguments)//[5, 10] [1, 2, 4] let s = 0 for(let i = 0; i < arguments.length; i++) { s += arguments[i] } console.log(s) } // 调用求和函数 sum(5, 10)// 两个参数 sum(1, 2, 4) // 两个参数 </script>
在上述代码中,我们调用了两次函数,第一次调用: sum(5, 10)
,那么argument = [5, 10]
第二次调用sum(1, 2, 4)
时,argument = [1, 2, 4]
。
但是这个arguement数组是一个伪数组,并不具备数组的一些方法,我们一般只对其读取内容。
剩余参数
JavaScript中提供了一个符号...
(展开运算符)。当其处于函数参数中时,会将剩余的参数整合为一个数组。
语法:
function fn(a, b, c, ...d){};
在上述语法中,d
就是一个剩余参数。
我列举几个传参情况,帮助大家理解:
调用fn(1,2,3,4,5,6,7,8,9,10)
在fn中只有四个参数,abcd,此时abc按照顺序与参数匹配:
a = 1
b = 2
c = 3
d = 4
多出来的
5,6,7,8,9,10
由于剩余参数d的存在,它们被整合为了一个数组:d= [5,6,7,8,9,10]
调用fn(1,2,3)
根据参数一一对应
a = 1
b = 2
c = 3
。那么d是什么呢?undefined吗?
并不是的,当剩余参数的变量没有匹配到参数时,其为一个空数组。
也就是
d = []
此外,剩余参数还有以下注意特点:
- 剩余参数是一个真数组,有数组的方法
- 剩余参数可以在箭头函数中使用
在实际应用中,我们更推荐使用剩余参数代替argument。