前言
在ES6中,我们引进了一种新的函数:箭头函数。箭头函数表达式的语法比普通函数表达式的语法更加简洁,并且没有自己的this,argument,super或new.target。箭头函数的表达式更适合那些本来需要匿名函数的地方,并且不能用他来作构造函数
什么是箭头函数
箭头函数相当于匿名函数,并且简化了函数的定义。箭头函数有两种定义的格式:
x => x * x
这种写法相当于:
function (x) {
return x * x
}
当箭头函数只包含一个表达式和参数时,我们可以省略()和 {...}和return
另一种写法:
x => {
if (x > 10) {
return x * x
} else {
return - x * x
}
}
当箭头函数包含多条语句的时候,这个时候就不能省略{...}和return
当参数只有一个的时候,()可以省略
(x) => {
return x + 1
}
与
x => {
return x + 1
}
是同样的意思
当需要返回一个一个对象的时候,写法如下:
x = ({foo : x})
箭头函数与普通函数的区别
This是可变的
箭头函数看上去是匿名函数的一种缩写,但实际上,箭头函数与普通函数有着很大的区别,箭头函数的this是词法作用域,由上下文确认,是不变的。普通函数的This是由调用的对象确认的,在函数定义时,无法确定普通函数的This指向,This的执行时可变的。
var name = 'zzz'
var a = {
name : 'hhh',
say : function () {
console.log('say:', this.name );
},
say1: () => {
console.log('say1', this.name);
}
}
a.say()
a.say1()
对于普通函数来说,内部的this指向函数运行时所在的对象。这对箭头函数并不成立,它没有自己的this对象,内部的this就是定义时上层作用域中的This。也就是说,普通函数的This是可变的,而箭头函数的This在定义时就决定好的,是不可变的。
没有自己的This
我们可以通过下面这个例子来看看箭头函数是否有自己的This
const obj = {
a : () => {
console.log(this);
}
}
obj.a()
const obj1 = {
a : function() {
console.log(this);
}
}
obj1.a()
对象obj1中没有使用箭头函数,直接输出他的this,因为是obj1调用函数a,所以输出的This指向为对象;对象obj中使用了箭头函数,它也输出了this,同时是对象调用这个函数,但它的This指向并不是对象,而是window。
如果箭头函数有自己的This,它输出也应该是object,但它输出的This指向是window,且箭头函数的This是它上一层作用域中的This。
箭头函数的This永远不会改变,call,apply,bind也无法改变
一般情况下,我们可以使用call,apply,bind来改变函数的this指向,但在箭头函数中,由于箭头函数的this在定义时就确认了,且永远指向它定义时的上层作用域中的this,所以这些方法无法改变箭头函数的this指向。
var name = 'zzz'
var a = {
name : 'hhh',
say : function () {
console.log(this.name);
},
say1 : () => {
console.log(this.name);
}
}
a.say.call({name: 666})
a.say1.call({name: 999})
我们在调用时,想通过call来改变函数的this指向,第一个函数say是一个普通函数,它经过call的调用,输出的值为666;第二个函数say1是一个箭头函数,它也经过了call的调用,但它输出的值还是zzz,说明箭头函数的this指向没有改变。箭头函数的this永远不会改变,即使使用call,apply,bind也无法改变。
没有arguments
一般普通函数中,都存在一个argument的类数组来存储调用函数时所传入的参数。
function b(b) {
console.log(arguments[0]);
}
b(2)
但在箭头函数中,没有arguments这个类数组。
let a = {
test: (a) => {
console.log(arguments[0]);
}
}
a.test(1)
虽然箭头函数没有自己的arguments,但我们可以通过箭头函数来访问外围函数的arguments
function constant() {
return () => arguments[0]
}
var result = constant(1)
console.log(result());
如果要访问箭头函数中的参数,可以通过命名参数,或是rest参数的形式访问参数
不能使用new关键字调用
在JS的函数内部有两个方法:call和constrouct
当我们通过new调用函数时,执行constrouct也就是构造器的方法来创建一个实例对象,然后再执行函数体,将this绑定到实体上。当直接调用时,执行call方法,直接执行函数体。
箭头函数并没有constrouct方法,不能被当做构造函数,如果通过new关键字来调用,则会报错。
var Foo = () => {}
var foo = new Foo()
没有原型
JS中所有的对象都是通过new关键字来创建的,每个函数都有一个属性prototype,但箭头函数没有。
var Foo = () => {}
console.log(Foo.prototype);
没有super
箭头函数连原型都没有,那自然就没有super来访问父类的属性。