箭头函数语法
基本写法:
(arg1, arg2) => {statements}
规则
- 当有参数且只有一个的时候,
()
可以省略x=>{...}
- 当函数体只有一个语句的时候,大括号可以不用写,而且
return
也可以省略;
x=>x + 1 // 等于 x=> {return x + 1}
- 在简写的单句函数体的情况下,如果返回值是一个对象,需要加上一个
()
x => ({a: x})
箭头函数语法的主要特点 —— this:
一句话,箭头函数没有 this
,
普通的函数中的 this,会根据我们执行它的时候的实际情况而改变;但是箭头函数没有 this,this 对它来说就是当前作用域下的一个普通的变量名。
换而言之,当我们写下一个箭头函数的时候,就算没有执行它,它内部的 this
已然确定
所以,当我们在全局环境下写下一个箭头函数的时候,它的 this 就是全局变量 window.
那么,如果我们在一个函数内部写一个箭头函数呢?
let a = 1
let b = {b: 1}
let c = {c: 1}
function normalFn(){
let arrowFn = () => console.log(this)
arrowFn()
}
normalFn.call(b)
normalFn.call(c)
为什么两次箭头函数的中 this 不一样呢?那是因为,函数 normalFn 每执行一次的时候,就会创建一个新的作用域,同时会创建一个新的 arrowFn,每个 arrowFn 中的 this 依然是它创建时候代码环境(在这里是局部)下的 this。
基于这个特点:
合适使用箭头函数的地方:
let a = 1
let b = {b: 1}
function normalFn(){
setTimeout(()=>{console.log(this)}, 100) // → {b: 1}
setTimeout(function (){console.log(this)}, 100) // → window
}
normalFn.call(b)
异步代码中的回调函数,如果是普通函数,那么它的回调函数在执行的时候 this 可能会变成 window;
而因为 arrowFn 中 this
是稳定的,所以它的 this
很符合我们的预期。
不合适使用的地方:
值得注意的是,箭头函数考虑的是作用域
,所以当我们在一个对象里面使用箭头函数作为方法的时候,它的 this
不是对象,而是对象所在作用域上的 this.
let a = {
fn: ()=>{console.log(this)}
}
a.fn() // window …
这也是为什么我们在 vue methods 中使用箭头函数的时候,我们得到的 this 不是当前组件,而是 undefined;
与此同时,我们已经不难理解:用call()、apply()、bind()这些方法在箭头函数身上是没用的。
箭头函数的其它特点:
-
没有arguments对象;
-
不可以当作构造函数;
-
箭头函数不能用作 Generator 函数,不可以使用yield命令;
-
异步箭头函数是可以的:
async () => {
// do something
}