JavaScript中,函数可以用箭头“=>”来定义,称之为箭头函数,有时候也称之为lambda表达式(lambda Expression)。箭头函数是一个匿名函数,其语法比函数表达式更简洁,相比函数表达式,箭头函数没有自己的 this、arguments、super或new.target。箭头函数更适用于那些需要匿名函数的地方,并且它不能用作构造函数。
//多个参数
(param1, param2, …, paramN) => { statements }
//只有一个参数
(param) => { statements }
//当只有一个参数时,圆括号可以省略
param => { statements }
//函数体只有一条 return语句
(param1, param2, …, paramN) => { return expression; }
//当函数体只有一条 return语句时,可以省略 return关键字和函数体的花括号
(param1, param2, …, paramN) => expression
//没有参数的函数必须写一对圆括号
() => { statements }
//加圆括号的函数体返回对象字面量表达式
params => ({foo: bar})
//支持剩余参数和默认参数
(param1, param2, …rest) => { statements }
(param1 = defaultValue1, param2, …, paramN = defaultValueN) => {
statements
}
//支持参数列表解构
let f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f(); // 6
在普通函数中,this总是指向调用它的对象,如果是构造函数,this指向创建的对象实例。箭头函数本身没有 this,但是它在声明时可以捕获其所在上下文的 this。例如:
var msg = "hello";
let func = () => {
console.log(this.msg);
};
func();//hello
在上面的代码中,箭头函数在全局作用域声明,所以它捕获全局作用域中的 this,this.msg即得到全局作用域中的 msg的值"hello"。
普通函数调用后都具有一个 arguments 对象存储实际传递的参数,但是箭头函数没有这个对象。在大多数情况下,可以使用rest参数来代替arguments对象。例如:
心箭头
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>实心箭头</title>
<style>
.con{
width: 300px;
height: 300px;
border: 1px solid #ccc;
margin: 50px auto;
background-color:#ccc;
}
.arrow-top{
border-bottom: 10px solid #fff;
border-right: 10px solid #fff;
border-left: 10px solid #fff;
border-top: 10px solid #ccc;
width: 0px;
height: 0px;
position: relative;
top:-40px;
left:100px;
}
.arrow-bottom{
border-bottom: 10px solid #fff;
border-right: 10px solid #fff;
border-left: 10px solid #fff;
border-top: 10px solid #ccc;
width: 0px;
height: 0px;
position: relative;
top:-40px;
left:100px;
}
</style>
</head>
<body>
<div class="con">
<div class="arrow-top"> </div>
</div>
</body>
</html>
非实心箭头
S6中,除了let和const新特性,箭头函数是使用频率最高的新特性了。如果你曾经了解如日中天的JavaScript衍生语言CoffeeScript, 就会清楚此特性并非ES6独创。箭头函数顾名思义是使用箭头(=>)定义的函数,属于匿名函数一类。
今天的文章内容将会从以下几个方面,介绍箭头函数:
本篇文章阅读时间预计8分钟
箭头函数有四种使用语法
1、单一参数的单行箭头函数
如下段代码所示,很简单:
const fn= foo =>`${foo} world`;
这是箭头函数最简洁的形式,常用于用作简单的处理函数,如过滤。如下段代码所示:
let array=['a','bc','def','ghij']; array=array.filter(item=>item.length>=2);
2、多参数的单行箭头函数 语法也很简单,如下段代码所示:
const fn=(foo,bar) => foo+bar
在实际开发中,函数的参数不会只有一个,在箭头函数中,多参数的语法跟普通函数一样,用括号包裹参数项。我们经常处理函数,如排序,示例代码如下:
let array=['a','bc','def','ghij']; array=array.sort((a,b) => a.length < b.length);
3、多行箭头函数 单一参数,如下段代码所示:
foo => { return `${foo} world`; }
多参数,如下段代码所示:
(foo,bar) => { return foo+bar; }
4、无参数箭头函数
如果一个箭头函数无参数传入,则需要用一对空的括号来表示空的参数列表。
const greet = () => 'Hello World'
以上都是被支持的箭头函数的表达方式,其最大的好处就是简单明了,省略了function关键字,而使用 => 代替。相对于传统的function函数,箭头函数在简单的函数使用中更为简洁直观。
书写箭头的函数过程中,我们应该注意以下几点:
1、使用单行箭头函数时,应避免换行
错误的用法,如下段代码所示:
const fn=x => x*2 //SyntaxError
正确的写法,如下:
const fn= x => x*2 //ok
2、参数列别的右括弧、箭头应在一行
错误的用法,如下段代码所示:
const fn = (x,y) //SyntaxError => { return x*y; }
下段代码书写是正确的:
const fn= (x,y) => { //ok return x*y } const fn= (x, y) => { //ok return x*y }
3、单行箭头函数返回只能包含一条语句
错误的书写,如下段代码所示:
const fn1= x => x=x*2; return x+2; //SyntaxError
正确的书写,如下段代码所示:
const fn2= x => { x=x*2; return x+2; } //ok
4、如果单行箭头返回一个对象,请用圆括号包裹
错误的书写,如下段代码所示,解析引擎会将其解析成一个多行箭头函数:
const ids=[1,2,3]; const users=ids.map(id=>{id:id}); //wrong:[ undefined, undefined, undefined ]
正确的书写,如下段代码所示:
const ids=[1,2,3]; const users=ids.map(id=>({id:id})); //Correct:[ { id: 1 }, { id: 2 }, { id: 3 } ]
箭头函数十分简洁,特别适合单行回调函数的定义,比如我们有以下需求:
我们有一个这样的名字数组names,['Will','Jack','Peter','Steve','John','Hugo','Mike'],输出序号为偶数的名字[ 'Will', 'Peter', 'John', 'Mike' ],我们如何使用箭头函数在一行语句完成呢,如下段代码所示:
const names=['Will','Jack','Peter','Steve','John','Hugo','Mike']; const newSet=names .map((name,index)=>({ id:index, name:name })) .filter(man => man.id %2 ==0) .map(man => [man.name]) .reduce((a,b) => a.concat(b))
事实上,箭头函数不仅书写简洁,还有一个神奇的功能,就是将函数内部的this延伸上一层作用域中(绑定最近的非箭头函数的上下文),及上一层的上下文会穿透到内层的箭头函数中,让我们先看一段实际的例子,如下段所示:
var Widget={ // A init:function () { // B document.addEventListener("click", function (event){ //C this.doSomething(event.type); }, false); }, doSomething:function (type) { console.log("Handling"+ type+"event"); } }; Widget.init();
这段代码会如何输出呢,想必大家都猜到了吧,输出undefined,为什么呢?我们在B位置内声明了函数(C区域),this关键词的指向B区域的函数,由于B区域内没有doSomething函数声明,因此输出undefined,ES6之前我们如何修正此问题呢?
我们可以使用bind方法改变this指向A区域Widget对象,示例代码如下:
var Widget={ // A init:function () { // B document.addEventListener("click", (function (event) { //C this.doSomething(event.type); }).bind(this), false); }, doSomething:function (type) { console.log("Handling"+ type+"event"); } }; Widget.init();
下面这种方法是我们最常用的方法,我们在B区域声明了that变量,并将其this赋值,确保c区域this的指向至Widget对象:
var Widget={ // A init:function () { // B var that=this; document.addEventListener("click", function (event) { //C that.doSomething(event.type); console.log(that); }, false); }, doSomething:function (type) { console.log("Handling"+ type+"event"); } }; Widget.init();
有了箭头函数,我们可以使用箭头函数的this穿透功能,将this的作用域延伸至上一层B区域函数,绑定最近的非箭头函数的上下文,如下段代码所示:
var Widget={ //A init:function () { //B document.addEventListener("click", (event) => { //C this.doSomething(event.type); }, false); }, doSomething:function (type) { console.log("Handling"+ type+"event"); } }; Widget.init();
箭头函数是不是更简单,代码更清晰呢。
还有一个情况需要注意,箭头函数对上下文的绑定是强制的,无法通过call或aplly进行改变,如下段代码所示:
function widget() { this.id=123; this.log=()=>{ console.log(this) console.log('widget log',this.id); } } var pseudoWidget={ id:456 }; new widget().log.call(pseudoWidget);//123
上述代码会如何输出呢,由于箭头函数对上下文的绑定是强制的,因此this指向不会指向pseudoWidget对象,因此输出123。
1、箭头函数作为匿名函数,是不能作为构造函数的,不能使用new
如下段代码所示,我们使用new方法,会提示如下信息:
const B =()=>({wechat:"前端达人"}); let b = new B(); //TypeError: B is not a constructor
2、箭头函数不绑定arguments,可以使用剩余参数(rest)解决
function A(a){ console.log(arguments); //[object Arguments] {0: 1} } var B = (b)=>{ console.log(arguments); //ReferenceError: arguments is not defined } var C = (...c)=>{ //...c即为rest参数 console.log(c); //[3] } A(1); B(2); C(3);
3、箭头函数this指向具备穿透特性,会捕获其所在上下文的this值
4、箭头函数没有原型属性
var a = ()=>{ return '前端达人'; } function b(){ return '前端达人'; } console.log(a.prototype);//undefined console.log(b.prototype);//object{...}
5、箭头函数不能当做Generator函数,不能使用yield关键字
6、箭头函数对上下文的绑定是强制的,无法通过call或aplly进行改变
小节
今天的内容就介绍到这里,我们可以看出使用箭头函能减少代码量,更加简介易读。在使用箭头函数时,我们一定要理解箭头函数和传统函数的区别,如果函数功能简单,只是简单的逻辑处理,尽量使用箭头函数。
更多精彩内容,请微信关注"前端达人”公众号!
*请认真填写需求信息,我们会在24小时内与您取得联系。