在ES6中,箭头函数是其中最有趣的新增特性。顾名思义,箭头函数是一种使用箭头(=>)定义函数的新语法,但是他与传统JavaScript函数有些许不同,主要集中在以下方面:
- 没有this、super、arguments和new.target绑定 箭头函数中this、super、arguments和new.target这些值由外围最近一层非箭头函数决定。 连原型都没有,自然也不能通过 super 来访问原型的属性,所以箭头函数也是没有 super 的,不过跟 this、arguments、new.target 一样,这些值由外围最近一层非箭头函数决定。
在箭头函数中,this引用的是定义箭头函数的上下文。
看下面例子,在对sayColor()的两次调用中,this引用的都是window对象,因为这个箭头函数是在window上下文中定义的:
window.color = 'red'
let o = {
color: 'blue'
}
let sayColor = () => console.log(this.color)
sayColor()
o.sayColor = sayColor
o.sayColor()
我们知道,在事件回调或者定时回调中调用某个函数,this值指向的并非想要的对象,次时将回调函数写成箭头函数就可以解决问题。这是因为箭头函数中的this会保留定义该函数时的上下文:
function King(){
this.royaltyName = 'Henry'
//this引用King的实例
settimeout (() => console.log(this.royaltyName),1000)
}
function Queen(){
this.royaltyName = 'Elizabeth'
//this引用指向window对象
settimeout (function() {console.log(this.royaltyName);}1000)
}
new King() //Henry
new Queen() //Elizabeth
- 不能通过new关键字调用 箭头函数没有[[Construct]]方法,所以不能被用作构造函数,如果通过new关键字调用箭头函数,程序会抛出错误。
JavaScript 函数有两个内部方法:[[Call]] 和 [[Construct]]。
当通过 new 调用函数时,执行 [[Construct]] 方法,创建一个实例对象,然后再执行函数体,将 this 绑定到实例上。
当直接调用的时候,执行 [[Call]] 方法,直接执行函数体。
箭头函数并没有 [[Construct]] 方法,不能被用作构造函数,如果通过 new 的方式调用,会报错。
var Foo = () => {};
var foo = new Foo(); // TypeError: Foo is not a constructor
- 没有原型 由于不可以通过new关键字调用箭头函数,因而没有构建原型的需求,所以箭头函数不存在prototype这个属性。 由于不能使用 new 调用箭头函数,所以也没有构建原型的需求,于是箭头函数也不存在 prototype 这个属性。
var Foo = () => {};
console.log(Foo.prototype); // undefined
- 不可以改变this的绑定 函数内部的this值不可以被改变,在函数的生命周期内始终保持一致。
- 不支持arguments对象 箭头函数没有arguments绑定,所以你必须通过命名参数和不定参数这两种形式访问函数的参数。 箭头函数没有自己的 arguments 对象,这不一定是件坏事,因为箭头函数可以访问外围函数的 arguments 对象:
function constant() {
return () => arguments[0]
}
var result = constant(1);
console.log(result()); // 1
那如果我们就是要访问箭头函数的参数呢?
你可以通过命名参数或者 rest 参数的形式访问参数:
let nums = (...nums) => nums;
- 不支持重复的命名参数 无论在严格模式还是非严格模式下,箭头函数都不支持重复的命名参数,而在传统函数的规定中,只有在严格模式下才不呢有重复的命名参数。