箭头函数与ES5 function的差异
首先我们会发现箭头函数有非常多可以使用的句法,我们一起看看下面的例子:
1. 无参数
在没有参数的情况下,可以直接在 =>前放置一个圆括号()
() => 42
甚至连括号都不需要
_ => 42
2. 单个参数
在单个参数情况下,圆括号是可选的:
x => 42 || (x) => 42
3. 多个参数
在多个参数情况下,圆括号是必须的:
(x, y) => 42
4. 函数语句
在箭头函数中,如果代码语句多于一条,就需要使用花括号包裹函数语句 ,而一旦你使用了花括号,你也需要在箭头函数中使用return返回对应的返回值。
这里有一个使用箭头函数的例子:
var feedTheCat = (cat) => {
if (cat === 'hungry') {
return 'Feed the cat';
} else {
return 'Do not feed the cat';
}
}
5. 输出对象
如果想返回一个对象,则需要用圆括号将对象包裹起来,这可以强制编译器解析圆括号中的内容并返回,而不是将花括号内当做函数语句。
x =>({ y: x })
匿名句法
我们需要注意到箭头函数是匿名的,这也意味着他们是没有函数名的,这也造成了一些问题:
1. 更难调试
当我们遇到BUG时,将不能根据函数名或发生异常的行数来定位异常函数的位置。
2. 无法调用自身
如果你需要在使用箭头函数中递归调用自身,那么你会发现这在箭头函数中是行不通的。
无绑定this
在ES6之前的函数this关键字指向会根据函数被调用的上下文环境决定。但是在箭头函数中,this在函数定义时绑定,这意味着箭头函数使用包裹箭头函数的外部代码中的this。
举个栗子,我们看下面的setTimeout方法:
// ES5
var obj = {
id: 42,
counter: function counter() {
setTimeout(function() {
console.log(this.id);
}.bind(this), 1000);
}
};
在ES5的例子中,.bind(this)
用来绑定this
上下文,如果不使用bind
的话,默认this
将会是undefined
。
// ES6
var obj = {
id: 42,
counter: function counter() {
setTimeout(() => {
console.log(this.id);
}, 1000);
}
};
箭头函数无法绑定this关键字,所以它会自动向上一层作用域寻找this,并使用上一层的this。
在何时应该避免使用箭头函数?
在一下几个情景你也许应该避免使用箭头函数:
1. 对象中的方法
当你调用cat.jumps,lives的数量并不会减少,这是因为this没有被绑定在cat对象上,而是使用父作用域的this。
var cat = {
lives: 9,
jumps: () => {
this.lives--;
}
}
运行结果:
2. 动态上下文的回调函数
如果是在动态上下文的回调中,箭头函数是不适用的,下面看一下栗子:
var button = document.getElementById('press');
button.addEventListener('click', () => {
this.classList.toggle('on');
});
这时点击按钮,会报错TypeError,这是因为this没有被绑定到按钮上。
3. 当箭头函数使你的代码可读性降低时
大量使用箭头函数,可能会对理解函数的含义造成障碍,这时可以考虑使用ES5函数增强可读性。
4. 用作构造函数时
箭头函数不可以作为构造函数,不可以使用new命令,否则会抛出一个错误。