最近被问到一道题,问箭头函数有什么特性,当时心想,这个我熟啊,随口就来了没有自己的 this 啊,和最近的 function 定义的函数相同啊,其实不止这个,有很多,我们虽然经常用,往往会忽略。所以今天就一起来了解下箭头函数。
总结版本
节约时间可以看这里!!和传统 JS 函数的不同点
- 不能通过 new 关键字调用, 没有原型
- 不可以改变 this 绑定,由外层非箭头函数决定,所以使用 call, apply, bind 也不会影响
- 不支持 arguments,所以根据作用域链,会拿到外层函数的 arguments
- 不支持重复命名参数
- 隐式返回
箭头函数是 ES6 引入的语法,和之前使用function
来定义的函数不同,箭头函数更加简洁,简单到甚至只需要一个() =>
举个例子
(a, b) => a + b
// 等价于
funtion(a, b){
return a + b
}
所以你看,它们两兄弟长得就不像,自然是有很多差异,来一起看看它的差异
隐式返回
看我们刚才那个例子,为啥我们在箭头函数中不用使用 return
就能返回 a + b
的值呢?
其实函数内部一直都有一个隐藏的返回值,使用 function
如果什么都不定义,其实默认就会返回 undefined
,我理解这是终止函数的执行,用代码来表示:
function noReturn() {
console.log('aaa')
return // 这个不需要手动写,不写默认就是
}
也就是说如果你在函数中没有需要 return
的,就会自动给你加上一个
那箭头函数函数有什么不同呢?
其实很明显就能看出来,箭头函数又给你省了一个 return
,适合这种函数体内只有一行代码的情况,多行还是需要写的
不过要注意,如果 return
的是一个值,不需要 {}
就可以
但是有一个注意的点,如果返回的是一个字面量需要加 ()
,看下面的例子
const add = (a, b) => a + b
const obj = () => ({ a: 1 })
This
嗯,this 就是我印象最深的了。
我们知道由于 JS 的特殊关系,this 是在运行时确定的,这往往会在代码中产生一些迷惑的行为。
我们在 function
函数里面访问 this 或者在嵌套函数里面访问 this 结果不太一样。this 在普通函数内总结为以下行为
- 在调用函数时使用 new 关键字,函数内的 this 是一个全新的对象。
- 如果 apply、call 或 bind 方法用于调用、创建一个函数,函数内的 this 就是作为参数传入这些方法的对象。
- 当函数作为对象里的方法被调用时,函数内的 this 是调用该函数的对象。
- 如果调用函数不符合上述规则,那么 this 的值指向全局对象(global object)。
- 浏览器环境下 this 的值指向 window 对象,但是在严格模式下
'use strict'
,this 的值为 undefined。
优先级按序号从高到低,this 比较复杂,这是另一个话题了,这里不展开讲了,我们主要来看箭头函数的不同
无论如何执行或在何处执行,箭头函数内部的 this
值始终等于离它最近的外部函数的 this
值。换句话说,箭头函数可按词法解析 this
,箭头函数没有定义自己的执行上下文。
这样的好处是啥呢,来举个例子
const obj = {
value: 2,
callback: function(arr) {
var self = this
function showThis() {
console.log(self.value)
}
showThis()
}
}
const obj2 = {
value: 2,
callback: function(arr) {
showThis = () => {
console.log(this.value)
}
showThis()
}
}
obj.callback() // 2
obj2.callback() // 2
这样就改善了我们之前在嵌套函数里面使用外面的 this 需要先定义变量的情况。
在类里面也经常使用,熟悉 React 的同学都知道,之前如果在类里面使用方法我们需要先 bind 一下 this, 但箭头函数都给我们解决了。
所以箭头函数的 this 是编写时确定的,所以使用 call, apply, bind 也不能改变
arguments
我们知道常规函数中,有一个 arguments
的类数组对象,包含了函数的所有参数,经常使用在我们没有具体定义参数的情况下,而箭头函数是不支持该对象的,所以如果你在箭头函数里面使用,按照作用域链的查找规则,会一直查询到最近的非箭头函数,然后实际使用的是非箭头函数里面的 arguments
为此,ES6 也提供了这种不定参数情况下的参数如果操作,看下面的例子
const add = (...args) => {
return args.reduce((cur, i) => cur + i, 0)
}
add(5, 10, 15)
...args
会把不定参数转换成一个数组,但使用这个也要注意,只能使用一次且放在所有参数末尾
不能使用 new & 没有原型
因为不能使用 new,所以箭头函数也没有原型,ES6 新增的 new.target 也没有,自然而然也不能通过 super 来访问原型属性
var Foo = () => {};
console.log(Foo.prototype); // undefined
嗯,这就是箭头函数和普通函数的区别了,感觉又打开了新世界