前言
es6中的一系列关于函数用法的变化是非常有趣的,在es6的新标准下,你可以更加轻便地使用函数,并且可以仿照面向对象编程的思想来使用函数,将函数转化为“类”。(这里的类加了引号,原因我们会在后面的学习中解释)下面就让我们来一起看一看es6下的函数有哪些有趣的变化。
1.箭头函数
箭头函数是es6下实现的一种新的函数书写方法。在过去的编程中,我们如果实现一个将数组内的字符串全部变成大写,需要这样的匿名函数进行实现:
const Marvel = ['spider man', 'iron man', 'thor', 'hulk', 'captain'];
const UpperMarvel = Marvel.map(function (name) {
return name.toUpperCase();
});
console.log(UpperMarvel); // Uppercase of all the elements in Marvel[]
现在,我们可以通过箭头函数来实现这一过程了:
const Marvel = ['spider man', 'iron man', 'thor', 'hulk', 'captain'];
const UpperMarvel = Marvel.map(
name => name.toUpperCase()
);
console.log(UpperMarvel);
可以看到,我们去掉了function关键字,去掉了参数的圆括号,函数体的花括号,以及return语句。直接采用: 参数 => 参数的操作,这一形式来代替之前冗长的匿名函数。 需要注意的是,我们并不是彻底抛弃了圆括号和花括号,在以下情况时,我们需要召回我们的括号兄弟:
- 当我们有不止一个参数时——需要圆括号
- 当我们的函数体不能用一个表达式完成,而需要多个语句时——需要花括号,而且我们需要召回return语句!
请看下面这个例子:
const Marvel = ['spider man', 'iron man', 'thor', 'hulk', 'captain'];
const UpperMarvel = Marvel.map(
name => {
name = name.toUpperCase();
return `${name} has ${name.length} characters in their name`;
});
console.log(UpperMarvel);
这里我们需要对name先进行大写处理,再通过模板字面量输出,多个语句,此时就必须有花括号出现。并且,由于我们当前花括号内的操作不再是一个单一表达式了,函数体必须由我们制定返回值,因此,return语句也是必不可少的!
2.箭头函数的this指针
提到this指针,还真是个非常头大的事情,对于初学者来说,javascript的第一个难点可能就在这里,很多人都不理解这个this指针到底是什么东西。我个人比较习惯把this理解为“所在地”,或者“你现在所处于”的意思,也就是说,它就是一个表示上下文环境的标志!我们来回顾一下在一般的javascript函数中,this都有哪些用法。
(1)当我们对某一对象调用方法的时候,例如Data.getName()
此时getName()函数中的this就指向对象Data。限定了当前大环境是Data对象,那么getName()得到的没准就是Data.name的值。
(2)Data1.getName().call(Data2),此时我们的call()方法传入了对象Data2,了解call()方法,你应该就明白这里我们虽然调用了 Data1的getName()方法,但是已经把this指向了Data2!
(3)this指向全局对象
以上是this指针在以往普通函数中的使用。那么在新的箭头函数中,this指针的规则有什么新的调整吗? 不难发现,在过去的函数中,this指针的指向取决于“怎么被调用,谁调用”,就像我们前面提到的Data.getName()一样,this指向Data。但在箭头函数中,this的指向更加直接,就是当前箭头函数的所在上下文环境! 我们通过一个例子就可以看出this指针在箭头函数中的用法:
function Latte() {
this.sugar = 0;
this.milk = 0;
}
Latte.prototype.addSugar = function () {
setTimeout(function () {
this.sugar++;
console.log('sugar added!');
}, 500);
};
const latte1 = new Latte();
latte1.addSugar();
setTimeout(function () {
console.log(latte1.sugar); // 0
}, 1000);
你可能会以为这里setTimeout函数中的this.sugar++已经给sugar属性增加了啊!为什么还是0呢,这个+1去哪里了?让我们想想前面提到的普通匿名函数中的this指针的情况。注意这里this指针出现在setTimeout的第一个参数匿名函数中,这意味着什么?这个里层的匿名函数的this指针,可和addSugar方法中的this指针不是一个东西哦!这个this指针本身是没有制定上下文的,它会直接被指向全局对象,那么这个+1就加给了全局对象中的sugar(实际上相当于undefined + 1 =NaN)。这里我们解决方法就是使用闭包,把addSugar的this指针**“塞进”**setTimeout的匿名函数中,比如通过建立一个新变量赋值为this,再在里层的匿名函数中使用这个变量代替this指针即可!
但是如果使用箭头函数,情况就不是上述这样了。牢记我们的箭头函数中的this指针永远指向当前所处函数的上下文!也就是你即便有一百个箭头函数嵌套在一起,最里面的this指针一样指向最外层的函数的上下文!我们看看同样的例子,换作匿名函数:
Latte.prototype.addSugar = function () {
setTimeout( () => {
this.sugar++;
console.log('sugar added!');
}, 500);
};
这里我们的sugar终于会+1了,原因就是我们的this指针会自动指向当前setTimeout所在的上下文,也就是addSugar的function的this内容,这样就可以找到我们的latte1对象中的sugar属性了!
3.默认参数函数
在es6中我们可以给函数进行默认函数参数的设定,尤其是和之前我们讲到的数组对象的解构结合起来的时候,你就会发现我们可以用很简单的代码实现一个参数灵活的函数!一个显示咖啡里面配料比重的函数:
function Latte(coffee = 30, sugar = 10, milk = 60){
return `this cup of latte contains ${coffee}% of coffee,${sugar}% of sugar and ${milk}% of milk`;
}
对应的输出如下:
console.log(Latte()); // this cup of latte contains 30% of coffee,10% of sugar and 60% of milk
console.log(Latte(15)); // this cup of latte contains 15% of coffee,10% of sugar and 60% of milk
console.log(Latte(15,25,45)); // this cup of latte contains 15% of coffee,10% of sugar and 60% of milk
这就是默然参数函数的用处,你不再需要像以往一样,分别讨论参数的缺省情况。现在你可以考虑一下,如果我们的参数包括数组和对象,那么通过之前学到的解构,是不是可以发挥更强大的作用?这个留给你自己去尝试一下! 以上就是es6中的一些函数方面的总结。