这篇学习笔记继续上一篇,为大家介绍es6给大家带来的一些实用功能,今天我们来简单说说箭头函数(=>)。我个人
非常喜欢这个功能,因为它可以使代码变得更简单,更容易阅读,而且某些时候还可以为我们解决javascript的一个
很头疼的问题:this问题。
1. 一些题外话
我们都知道es6是近两年才开始普及的javascript版本,虽然目前的几大浏览器都开始支持es6,但是旧版本的浏览器
和一些其他平台上却没有办法支持es6,那是不是这意味着我们如果要从兼容性方面考虑的话,就不应该使用es6了呢?
并不是!因为有这么一款神器的工具叫babel,它可以将es6甚至是es7的一部分新语法转换成es5,让我们简单来看一下
babel的网站:英文版:http://babeljs.io/,中文版:http://babeljs.cn/
这里需要讲一下,我建议如果你决定使用es6的话,就一定要会用babel,而幸运的是,网上babel的教程非常多,而且
babel本身也不是很难上手。这里我们先进入babel中文网站,然后点击最上面的“在线实验”,你会看到有两个在线编辑器
我们可以在左边的编辑器里打入我们想测试的es6代码,右边就会输出babel转换以后的es5代码,我们可以用这种方法
了解babel是如何把我们的es6代码进行转换的,举例来说,我在左边输入let a = 'hello world'
,右边就会显
示出var a = 'hello world'
,是不是很方便。但是要注意的是,这个在线实验只是个“山寨版”,真正的babel比
它要强大的多,所以千万不要把写好的es6代码简单的复制,粘贴到这里,然后把转换出来的es5贴回去。如果想使用
babel,最好还是使用它的命令行工具,官网里面有详细的介绍。
2. 用箭头函数简化代码
2.1 初识箭头函数
我们先来写一个最最简单的加法function,1
2
3
4
5const double = function(a){
return a*2;
}
console.log(double(3)); //这里会输出6
大家来看一下这个function,就算是这么简单的逻辑,我们还是一样要写function,return,各种大括号和小括号。是
不是感觉特别麻烦。这就是箭头函数存在的一个意义。我们来看一下箭头函数的版本应该怎么写:
1 | const addition = (a)=>{ |
是不是感觉清爽了一点?其实这里只是刚开始,其实还没怎么开始简化。我们去掉function这个词,但后在参数后面加上一个
粗箭头(=>),其实就是一个等于号加上一个大于号,就这么简单。其实它不仅仅省去了function这个单词,请仔细看箭头这
段代码,是不是感觉有点像函数式?箭头左边是输入,右边是输出,在这个例子里面,就是输入一个数,然后输出它的两倍。而
function本身不就是函数的意思么?这样是不是比function(a){...}
更直观了呢?其实javascript里面有一个流派,
叫做函数式编程,这个流派会大量的使用这种函数式,让代码尽量符合输入=>输出这种函数的理念,同时尽可能的少使用面向对
象的概念,代码变得更纯净并且更好预测(给你一个函数,相同的输入一定会产出相同的输出)。
2.2 进一步简化
如果你并不关心所谓函数式编程,只是想简化代码,而且觉得仅仅这样还不过瘾的话,别着急,我们的代码其实还能继续简化,这
里说一下箭头函数的第二个简化规则:如果箭头右边的函数体只有一行代码并且需要return一个东西的话,那么我们可以去掉大括
号和return关键字,代码就变成了这样:1
2
3const addition = (a)=> a*2;
console.log(double(3)); //这里会输出6
对,就一行,更简洁了吧?这里再强调一下,你的代码体只有一行的时候,才能去掉大括号,如果多于一行,那么大括号和return
都必须保留。第二,如果你像上面一样,只写一行的话,那就意味着=>右边是你要return的内容,并且一定会return。还没完
呢,箭头函数还有第三个简化规则,就是如果你函数的参数(arguments)只有一个的话,那么你可以去掉小括号,代码就变成
了这样:1
2
3const addition = a=> a*2;
console.log(double(3)); //这里会输出6
怎么样?这样够简洁了吧!原来的function{…}直接变成了一个算术式。
3. 用箭头函数改变this指针
还是照例先上一段代码:1
2
3
4
5
6
7
8
9
10
11const person = {
name: 'John',
skills: ['javascript', 'html', 'css'],
sayHello: function(){
return this.skills.forEach(function(skill){
console.log(this.name+' knew '+ skill);
})
}
};
person.sayHello();
这段代码很简单,就是我们定义了一个object,然后有name和skills两个属性,其中skills是一个数组,里面有三个字符串,
然后我们在这个object上面定义一个sayHello的方法,对于skills数组里的每一个skill输出一段话,这里可以看到,我们
用了之前说过的forEach方法对数组进行迭代。但是,在我们执行这段代码的时候,会发现输出结果是这样的:1
2
3knew javascript
knew html
knew cssthis.name
并没有输出,我们在console.log(this.name+' knew '+ skill);
之前加上console.log(this);
会
发现,this输出的是window或者global。这其实是因为forEach里面的那个function是回调函数,回调函数的this指向的是全
局上下文,在node环境里运行就是global,在浏览器运行就是window。
如果想让它正常的输出,我们通常会用这两种办法:
bind改变this指针:
1
2
3
4
5
6
7
8
9
10const person = {
name: 'John',
skills: ['javascript', 'html', 'css'],
sayHello: function(){
return this.skills.forEach((function(skill){
console.log(this);
console.log(this.name+' knew '+ skill);
}).bind(this))
}
};对this进行缓存:
1
2
3
4
5
6
7
8
9
10
11const person = {
name: 'John',
skills: ['javascript', 'html', 'css'],
sayHello: function(){
var self = this;
return this.skills.forEach(function(skill){
console.log(self);
console.log(self.name+' knew '+ skill);
})
}
};
这两种方法我们应该都很熟悉吧。好,我们来改写一下sayHello这个方法,用箭头函数来代替function:1
2
3
4
5
6
7
8const person = {
name: 'John',
sayHello: function(){
return this.skills.forEach(skill=>{
console.log(`${this.name} knew ${skill}`);
})
}
};
当你用之前的person.sayHello()
方法调用时,你会发现这个方法输出的是正确的,而且如果你试着在箭头函数里面输出
this时,发现它输出的是peron这个对象。这就是箭头函数的另一大特性,改变this指针,把this改变成这个function外面
一层的执行上下文。也可以这么理解,箭头函数不会创建独立的上下文,而是引用的外层的上下文。
我们再来看一个例子,这个例子证明了改变this指针未必总是好的:1
2
3
4
5
6
7
8
9
10const person = {
name: 'john',
getName: function(){
return this.name;
},
getNameArrow: ()=>this.name
};
console.log(person.getName());//这里正常输出john
console.log(person.getNameArrow());//这里无法输出
getName和getNameArrow唯一的区别就是一个用了箭头函数,一个用了普通的function。而用了箭头函数的getNameArrow中
this指针指向的是外层上下文,也就是全局上下文,而全局上下文里面没有name这个属性,所以无法正常输出。
4. 适合与不适合用箭头函数的情况
从上面的例子,我们能看出来,不是所有时候都要用箭头函数的,这里我大概向大家介绍一下我一般会在什么时候用箭头函数,什么
时候舍弃箭头函数而用普通的function函数
1)回调函数中适合使用箭头函数。这样可以使代码变得更简洁,更容易理解,比如forEach,map这些方法都需要传入一个回调函数
这就是一个使用箭头函数的好机会。
2) 高阶函数适合使用箭头函数,我们来看个例子:1
2
3
4
5
6
7
8
9
10
11
12
13//这是不用箭头函数的写法
const add = function(a){
return function(b){
return a+b;
}
};
console.log(add(2)(3));
//这是使用箭头函数的写法
const add = a=>b=>a+b;
console.log(add(2)(3));
代码看着是不是简单了很多。
3)在涉及到this时,除非需要使用apply,call或者bind去改变this指针,否则尽量不要用箭头函数。
总结
今天和大家简单的介绍了一下es6的又一个新功能:箭头函数,为什么要使用箭头函数,以及使用箭头函数简化代码的几个规则,并且给
大家看了箭头函数的另外一个功能:改变this指针。并且简单聊了一下我个人什么时候会用箭头函数,什么时候不会用,希望大家在以后
的工作和学习中可以尽量去尝试使用箭头函数,这样既可以简化代码,又可以使代码变得更清晰。