箭头函数
2022年7月30日大约 3 分钟
1.没有原型
1.没有prototype
(原型),所以箭头函数本身没有 this
、super
let arrow = () =>{}
console.log(arrow.prototype) // undefined
2.this 指向定义时的上层作用域
this
指向 定义时所在 的上层作用域:
- 如果箭头函数被非箭头函数包含:
this
指向 定义时所在的 最近一层非箭头函数的this
值 - 如果箭头函数外层没有普通函数:
this
指向全局作用域
箭头函数的函数体是一层作用域,它的上层作用域即箭头函数定义所在的作用域
let a // 声明全局变量 a 用于存放箭头函数的地址
let obj1 = { name: 'obj1' }
// obj1 调用 foo1,foo1 中将箭头函数赋值给 a
foo1.call(obj1)
let obj2 = { name: 'obj2' }
// obj2 调用 foo2,foo2 中调用全局变量 a 所指向的箭头函数
foo2.call(obj2)
function foo1() {
// 箭头函数 this 指向函数定义时所在的最近一层非箭头函数的 this 值
// 又通过 call 显式指定 foo1 调用者,所以 foo1 this 值指向 obj1
a = () => {
console.log(this.name)
}
}
function foo2() {
// 箭头函数 this 指向与调用位置无关
a()
}
// 打印 obj1
普通函数的 this 值只有在函数执行时才能确定调用者,而不是在函数定义时确定,箭头函数就是要打破这一规则,方便开发,比如在 setTimeout 中使用箭头函数:
var name = 'window' // 挂载到 window 上
// 默认绑定
const obj1 = {
name: 'obj1',
delay() {
setTimeout(function() {
console.log(this.name)
}, 0) // setTimeout 传入普通函数,则是独立函数调用,指向 window
}
}
obj1.delay() // 'window'
// 箭头函数外层有普通函数
const obj2 = {
name: 'obj2',
delay() {
setTimeout(() => {
console.log(this.name)
}, 0)
}
}
obj2.delay() // 'obj2'
// 箭头函数外层没有普通函数
const fn = () => console.log(this.name)
fn() // 'window'
注意
块语句,如 if(){}
、字面量对象 let obj = {}
等不会产生作用域
作用域有:全局、函数、块、eval 作用域
3.没有参数列表
没有 arguments
,可以使用 rest参数…
获取参数列表
// 普通函数
function fn1(args){
console.log(arguments)
}
fn1(1,2,3)// [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
// rest参数...
let fn2 = (num1, num2, ...args) => {
console.log(args)
}
fn2(1,2,3,4,5) // [3,4,5]
4.不能指定 this 指向
不能通过 call、apply、bind
改变 this
指向
5.不能 new 调用
不能通过 new
调用,箭头函数不能作为构造函数使用,所以也没有 new.target
new.target
是ES6新引入的属性,普通函数如果通过new
调用,new.target
会返回该函数的引用。此属性主要:用于确定构造函数是否为new调用的。
6.不能重命名函数参数
普通函数的函数参数支持重命名,后面出现的会覆盖前面的,箭头函数会抛出错误:
function fn1(a, a) {
console.log(a, arguments) // 2 [1,2]
}
let fn2 = (a, a) => {
console.log(a) // 报错:在此上下文中不允许重复参数名称
}
fn1(1, 2)
fn2(1, 2)