function name(parameters) { // function body }
普通匿名函数则没有函数名,匿名函数通常会被赋值给一个变量/属性,有时候还会被直接调用:
var example = function (parameters) { // function body }
ES6 为我们提供了一种写匿名函数的新方法,即箭头函数。箭头函数不需要使用function关键字,其参数和函数体之间以=>相连接:
var example = (parameters) => { // function body }
尽管箭头函数看起来类似于传统的匿名函数,他们却具有根本性的不同:
箭头函数不能被直接命名,不过允许它们赋值给一个变量;
箭头函数不能用做构造函数,你不能对箭头函数使用new关键字;
箭头函数也没有prototype属性;
箭头函数绑定了词法作用域,不会修改this的指向。
最后一点是箭头函数最大的特点,我们来仔细看看。
词法作用域
我们在箭头函数的函数体内使用的this,arguments,super等都指向包含箭头函数的上下文,箭头函数本身不产生新的上下文。下述代码中,我们创建了一个名为timer的对象,它的属性seconds用以计时,方法start用以开始计时,若我们在若干秒后调用start方法,将打印出当前的seconds值。
// ES5 var timer = { seconds: 0, start() { setInterval(function(){ this.seconds++ }, 1000) } } timer.start() setTimeout(function () { console.log(timer.seconds) }, 3500) > 0
// ES6 var timer = { seconds: 0, start() { setInterval(() => { this.seconds++ }, 1000) } } timer.start() setTimeout(function () { console.log(timer.seconds) }, 3500) // <- 3
第一段代码中start方法使用的是常规的匿名函数定义,在调用时this将指向了window,console出的结果为undefined,想要让代码正常工作,我们需要在start方法开头处插入var self = this,然后替换匿名函数函数体中的this为self,第二段代码中,我们使用了箭头函数,就不会发生这种情况了。
还需要说明的是,箭头函数的作用域也不能通过.call,.apply,.bind等语法来改变,这使得箭头函数的上下文将永久不变。
我们再来看另外一个箭头函数与普通匿名函数的不同之处,你猜猜,下面的代码最终打印出的结果会是什么:
function puzzle() { return function () { console.log(arguments) } } puzzle('a', 'b', 'c')(1, 2, 3)
答案是1,2,3,原因是对常规匿名函数而言,arguments指向匿名函数本身。
作为对比,我们看看下面这个例子,再猜猜,打印结果会是什么?