也许我们已经习惯了在定义函数时使用:
function f(){
...
}
这样的写法。但是ES6 提供了新的函数定义方法,即箭头函数。不仅在写法上简化了代码量,而且更重要的是提供了新的this指向。大家可以对比我之前的文章JS入门难点解析7-this进行阅读。
箭头函数的基本用法如下:
参数部分使用一对圆括号包围,函数体部分使用一对花括号包围,参数与函数体使用箭头连接。
var add = (num1, num2) => {
var sum = num1 + num2
return sum;
};
等同于
var add = function(num1, num2) {
var sum = num1 + num2
return sum;
};
如果参数没有参数,仅需一对圆括号即可:
var getFive = () => {
return 5;
};
如果仅有一个参数,可以省略圆括号:
var getNum= num => {
return num;
};
如果函数体只有一条语句,可以省略花括号
var getNum= num => num;
我们来看一个例子:
function foo() {
setTimeout(function() {
console.log('id:', this.id);
}, 100);
}
var id = 21;
foo.call({ id: 42 });
// id: 21
这段代码中,foo的this指向的是{id: 42},但是setTimeout中的匿名函数在执行时其this指向的是全局。(可以参考我的文章JS入门难点解析7-this)但是,如果从写代码的人的角度去思考,很明显是希望此处匿名回调函数的this是指向call的对象的。
箭头函数可以让setTimeout里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域。
function foo() {
setTimeout(() => {
console.log('id:', this.id);
}, 100);
}
var id = 21;
foo.call({ id: 42 });
// id: 42
看上去很神奇,仿佛箭头函数改变了this的绑定。但其实不然。this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。正是因为它没有this,所以也就不能用作构造函数。
所以,箭头函数转成 ES5 的代码如下。
// ES6
function foo() {
setTimeout(() => {
console.log('id:', this.id);
}, 100);
}
// ES5
function foo() {
var _this = this;
setTimeout(function () {
console.log('id:', _this.id);
}, 100);
}
上面代码中,转换后的 ES5 版本清楚地说明了,箭头函数里面根本没有自己的this,而是引用外层的this。所以这种this的固定化是一种语法糖,本质上和我们以前使用的var that = this;的写法是一致的。
箭头函数可以让this指向固定化的特性很有利于封装回调函数。下面是一个例子,DOM 事件的回调函数封装在一个对象里面。
var handler = {
id: '123456',
init: function() {
document.addEventListener('click',
event => this.doSomething(event.type), false);
},
doSomething: function(type) {
console.log('Handling ' + type + ' for ' + this.id);
}
};
上面代码的init方法中,使用了箭头函数,这导致这个箭头函数里面的this,总是指向handler对象。否则,回调函数运行时,this.doSomething这一行会报错,因为此时this指向document对象。
箭头函数有几个使用注意事项。
(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替(就是使用展开符)。
(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。