Appearance
箭头函数
ECMAScript 6 标准新增了一种新的函数:Arrow Function(箭头函数)
js
let func = x => x
// 相当于
let func = function(x) {
return x
}
// babel中编译
var func = function func(x) {
return x
}
特点
- 箭头函数相当于匿名函数,并且简化了函数定义,并且没有自己的 this、arguments、super 或者 new.target
我们通过 babel 去观看箭头函数的转换
js
// ES6
;() => {
console.log(this.a)
console.log(arguments)
}
;(...ret) => {
console.log(ret)
}
c => c
var Foo = () => {}
var foo = new Foo() // TypeError: Foo is not a constructor
// 装换后的
;("use strict")
var _arguments = arguments,
_this = void 0
;(function() {
console.log(_this.a)
console.log(_arguments)
})
;(function() {
for (var _len = arguments.length, ret = new Array(_len), _key = 0; _key < _len; _key++) {
ret[_key] = arguments[_key]
}
console.log(ret)
})
;(function(c) {
return c
})
var Foo = function Foo() {}
var foo = new Foo() // 这个时候是可以的
我们通过上面 babel 的转换可以看出
- 为什么没有自己的 this
通过将箭头函数中 this 全都修改成外部作用域中的 _this
,所以就没有自己的 this 而是指向外部作用域
js
window.name = "windowName"
let name = "globalName"
let obj = {
name: "app",
jumps: () => {
console.log(this.name)
},
junpsFun() {
console.log(this.name)
},
}
//
obj.jumps() // windowName
obj.junpsFun() // app
- arguments 跟 this 一样
js
var _arguments = arguments,
_this = void 0
;(function() {
console.log(_this.a)
console.log(_arguments)
})
- 不能通过 new 关键字调用
但是通过 babel 转换的
js
// ES6
var Foo = () => {}
var foo = new Foo() // TypeError: Foo is not a constructor
// 装换后的
var Foo = function Foo() {}
var foo = new Foo() // 这个时候是可以的
其实还是可以使用 new 去实例化一个实例的,所以有些时候 Babel 与真正的是不一样的
- 箭头函数不能访问 arguments 对象,那么我们可以通过...rest 来存储所有参数,并获取
js
const getArgs = () => arguments
getArgs("1", "2", "3") // ReferenceError: arguments is not defined
const getArgs2 = (...rest) => rest
getArgs("1", "2", "3") // ["1", "2", "3"]
真正的箭头函数
- 没有 this
箭头函数没有 this,所以需要通过查找作用域链来确定 this 的值。
- 没有 arguments
箭头函数没有自己的 arguments 对象,这不一定是件坏事,因为箭头函数可以访问外围函数的 arguments 对象
如果访问自己的 arguments 通过命名参数或者 rest 参数的形式访问参数:
js
let nums = (...nums) => nums
- 不能通过 new 关键字调用
JavaScript 函数有两个内部方法:[[Call]] 和 [[Construct]]。
当通过 new 调用函数时,执行 [[Construct]] 方法,创建一个实例对象,然后再执行函数体,将 this 绑定到实例上。
当直接调用的时候,执行 [[Call]] 方法,直接执行函数体。
箭头函数并没有 [[Construct]] 方法,不能被用作构造函数,如果通过 new 的方式调用,会报错。
- 没有 new.target
因为不能使用 new 调用,所以也没有 new.target 值。
- 没有原型
由于不能使用 new 调用箭头函数,所以也没有构建原型的需求,于是箭头函数也不存在 prototype 这个属性。
- 没有 super
连原型都没有,自然也不能通过 super 来访问原型的属性,所以箭头函数也是没有 super 的,不过跟 this、arguments、new.target 一样,这些值由外围最近一层非箭头函数决定。
小知识
当箭头函数箭头后面是简单操作时,直接去掉“{ }”,这样可以不使用 return 就能会返回值
js
// 箭头函数常规写法
console.log(
Array.from([1, 2, 3], x => {
return x + x
})
) // expected output: Array [2, 4, 6]
// 箭头函数简单操作
console.log(Array.from([1, 2, 3], x => x + x)) // expected output: Array [2, 4, 6]
不适用箭头函数的地方
有哪些时候我们不适用箭头函数
对象的方法
原型上的方法
事件回调
需要访问构造函数(new)