ES6标准 Arrow Function(箭头函数=>)
ES6—箭头函数
0.为什么会出现箭头函数?
1.传统的javascript函数语法并没有提供任何的灵活性,每一次你需要定义一个函数时,你都必须输入function(){},这至少会出现两个问题,ES6箭头函数都圆满解决了它,
第一个问题:代码输入快了容易输错成funciton或者functoin或者其它,但是=>这个玩意你要是再写错就只能说有点过分了。
第二个问题:节省大量代码,我们先不用管下面的ES6代码为什么这样的语法能实现同样的功能,我们就直观的感受一下代码量。
ES5写法:
functionaddFive(num){ returnnum+5; } alert(addFive(10));
ES6写法:
varaddFive=num=>num+5; alert(addFive(5));
没有function、没有return,没有(),没有{},这些全变成了浮云,世界好清静。
从上面我们就可以看到,使用箭头函数不仅仅能够避免错误,同时还能让我们少一丢丢代码,当然实际工作中远比这个代码量节省更多。
一方面是因为积累效应,每一部分少一丢丢合起来就多了,一方面是它还有更能节省代码和大幅提高工作效率的场景。
接下来我们就说说今天的主角--箭头函数。
ES6标准新增了一种新的函数:ArrowFunction(箭头函数),也称“胖箭头函数”,允许
使用“箭头”(=>)定义函数,是一种简写的函数表达式。
1、箭头函数语法
在ES5中我们实现一个求和的函数:
varsum=function(x,y){ returnx+y }
要使用箭头函数,可以分两步实现同样的函数功能:
首先使用=>来替代关键词function
varsum=(x,y)=>{ returnx+y }
这个特性非常好!!!
前面我们已经说过用=>来替代关键词function就意味着不会写错function了,这真是一个绝妙的设计思想!
其次,函数体只有一条返回语句时,我们可以省略括号{}和return关键词:
varsum=(x,y)=>x+y
再夸张一点点,如果只有一个参数时,()可省略。
这是箭头函数最简洁的形式,常用于作用简单的处理函数,比如过滤:
//ES5 vararray=['1','2345','567','89']; array=array.filter(function(item){ returnitem.length>2; }); //["2345","567"] //ES6 letarray=['1','2345','567','89']; array=array.filter(item=>item.length>2); //["2345","567"]
箭头函数的主要使用模式如下:
//一个参数对应一个表达式 param=>expression;//例如x=>x+2; //多个参数对应一个表达式 (param[,param])=>expression;//例如(x,y)=>(x+y); //一个参数对应多个表示式 param=>{statements;}//例如x=>{x++;returnx;}; //多个参数对应多个表达式 ([param][,param])=>{statements}//例如(x,y)=>{x++;y++;returnx*y;}; //表达式里没有参数 ()=>expression;//例如varflag=(()=>2)();flag等于2 ()=>{statements;}//例如varflag=(()=>{return1;})();flag就等于1 //传入一个表达式,返回一个对象 ([param])=>({key:value}); //例如varfuc=(x)=>({key:x}) varobject=fuc(1); alert(object);//{key:1}
大家不要觉得好多啊,好麻烦,其实这些根本不复杂。投入一次,受益终生。(怎么感觉我像卖保险的……),写一两次你就习惯新的写法了。
2、箭头函数中的this
箭头函数内的this值继承自外围作用域。运行时它会首先到它的父作用域找,如果父作用域还是箭头函数,那么接着向上找,直到找到我们要的this指向。
我们先看一道经典的关于this的面试题:
varname='leo'; varteacher={ name:"大彬哥", showName:function(){ functionshowTest(){ alert(this.name); } showTest(); } }; teacher.showName();//结果是leo,而我们期待的是大彬哥,这里this指向了window,我们期待指向teacher
大家知道,ES5中的this说好听了叫"灵活",说不好听就是瞎搞,特别容易出问题.而且面试还非常爱考,工作更不用说了,经常给我们开发捣乱,出现不好调试的bug,用E箭头函数解决这个问题就很得心应手了。
varname='leo'; varteacher={ name:"大彬哥", showName:function(){ letshowTest=()=>alert(this.name); showTest(); } }; teacher.showName();
箭头函数中的this其实是父级作用域中的this。箭头函数引用了父级的变量词法作用域就是一个变量的作用在定义的时候就已经被定义好,当在本作用域中找不到变量,就会一直向父作用域中查找,直到找到为止。
由于this在箭头函数中已经按照词法作用域绑定了,所以,用call或者apply调用箭头函数时,无法对this进行绑定,即传入的第一个参数被忽略:
varobj={ birth:1996, getAge:function(year){ varb=this.birth;//1996 varfn=(y)=>y-this.birth;//this.birth仍是1996 returnfn.call({birth:1990},year); } }; obj.getAge(2018);//22(2018-1996)
由于this已经在词法层面完成了绑定,通过call或apply方法调用一个函数时,只是传入了参数而已,对this并没有什么影响。因此,这个设计节省了开发者思考上下文绑定的时间。
3、箭头函数的特性
3.1箭头函数没有arguments
箭头函数不仅没有this,常用的arguments也没有。如果你能获取到arguments,那它
一定是来自父作用域的。
functionfoo(){ return()=>console.log(arguments) } foo(1,2)(3,4)//1,2
上例中如果箭头函数有arguments,就应该输出的是3,4而不是1,2。
箭头函数不绑定arguments,取而代之用rest参数…解决
varfoo=(...args)=>{ returnargs } console.log(foo(1,3,56,36,634,6))//[1,3,56,36,634,6]
箭头函数要实现类似纯函数的效果,必须剔除外部状态。我们可以看出,箭头函数除了传入的参数之外,真的在普通函数里常见的this、arguments、caller是统统没有的!
如果你在箭头函数引用了this、arguments或者参数之外的变量,那它们一定不是箭头函数本身包含的,而是从父级作用域继承的。
3.2箭头函数中不能使用new
letPerson=(name)=>{ this.name=name; }; letone=newPerson("galler");
运行该程序,则出现TypeError:Personisnotaconstructor
3.3箭头函数可以与变量解构结合使用。
constfull=({first,last})=>first+''+last; //等同于 functionfull(person){ returnperson.first+''+person.last; } full({first:1,last:5})//'15'
3.4箭头函数没有原型属性
varfoo=()=>{}; console.log(foo.prototype)//undefined
由此可以看出箭头函数没有原型。
另一个错误是在原型上使用箭头函数,如:
functionA(){ this.foo=1 } A.prototype.bar=()=>console.log(this.foo) leta=newA() a.bar()//undefined
同样,箭头函数中的this不是指向A,而是根据变量查找规则回溯到了全局作用域。同样,使用普通函数就不存在问题。箭头函数中不可加new,也就是说箭头函数不能当构造函数进行使用。
3.5箭头函数不能换行
varfunc=() =>1;//SyntaxError:expectedexpression,got'=>'
如果开发中确实一行搞不定,逻辑很多,就加{},你就想怎么换行怎么换行了。
varfunc=()=>{ return'来啊!互相伤害啊!';//1.加{}2.加return }
4、箭头函数使用场景
JavaScript中this的故事已经是非常古老了,每一个函数都有自己的上下文。
以下例子的目的是使用jQuery来展示一个每秒都会更新的时钟:
$('.time').each(function(){ setInterval(function(){ $(this).text(Date.now()); },1000); });
当尝试在setInterval的回调中使用this来引用DOM元素时,很不幸,我们得到的只是一个属于回调函数自身
上下文的this。一个通常的解决办法是定义一个that或者self变量:
$('.time').each(function(){ varself=this; setInterval(function(){ $(self).text(Date.now()); },1000); });
但当使用箭头函数时,这个问题就不复存在了。因为它不产生属于它自己上下文的this:
$('.time').each(function(){ setInterval(()=>$(this).text(Date.now()),1000); });
箭头函数的另一个用处是简化回调函数。
//正常函数写法 [1,2,3].map(function(x){ returnx*x; }); //箭头函数写法 [1,2,3].map(x=>x*x);
当然也可以在事件监听函数里使用:
document.body.addEventListener('click',event=>console.log(event,this));
//EventObject,BodyElement
5、总结
5.1箭头函数优点
箭头函数是使用=>语法的函数简写形式。这在语法上与C#、Java8、Python(lambda函数)和CoffeeScript的
相关特性非常相似。
非常简洁的语法,使用箭头函数比普通函数少些动词,如:function或return。
()=>{...}//零个参数用()表示。
x=>{...}//一个参数可以省略()。
(x,y)=>{...}//多参数不能省略()。
如果只有一个return,{}可以省略。
更直观的作用域和this的绑定,它能让我们能很好的处理this的指向问题。箭头函数加上let关键字的使用,将会让我们javascript代码上一个层次。
5.2箭头函数使用场景
箭头函数适合于无复杂逻辑或者无副作用的纯函数场景下,例如用在map、reduce、filter的回调函数定义
中,另外目前vue、react、node等库,都大量使用箭头函数,直接定义function的情况已经很少了。
各位同学在写新项目的时候,要不断的琢磨箭头函数使用场景、特点,享受使用箭头函数带来的便利,这样才能更快地成长。
下面是廖雪峰网站的补充
ES6标准新增了一种新的函数:ArrowFunction(箭头函数)。
为什么叫ArrowFunction?因为它的定义用的就是一个箭头:
x=>x*x
上面的箭头函数相当于:
function(x){
returnx*x;
}
在继续学习箭头函数之前,请测试你的浏览器是否支持ES6的ArrowFunction:
箭头函数相当于匿名函数,并且简化了函数定义。箭头函数有两种格式,一种像上面的,只包含一个表达式,连{...}和return都省略掉了。还有一种可以包含多条语句,这时候就不能省略{...}和return:
x=>{ if(x>0){ returnx*x; } else{ return-x*x; } }
如果参数不是一个,就需要用括号()括起来:
//两个参数: (x,y)=>x*x+y*y //无参数: ()=>3.14 //可变参数: (x,y,...rest)=>{ vari,sum=x+y; for(i=0;i如果要返回一个对象,就要注意,如果是单表达式,这么写的话会报错:
//SyntaxError:
x=>{foo:x}因为和函数体的{...}有语法冲突,所以要改为:
//ok:
x=>({foo:x})this
箭头函数看上去是匿名函数的一种简写,但实际上,箭头函数和匿名函数有个明显的区别:箭头函数内部的this是词法作用域,由上下文确定。
回顾前面的例子,由于JavaScript函数对this绑定的错误处理,下面的例子无法得到预期结果:
varobj={ birth:1990, getAge:function(){ varb=this.birth;//1990 varfn=function(){ returnnewDate().getFullYear()-this.birth;//this指向window或undefined }; returnfn(); } };现在,箭头函数完全修复了this的指向,this总是指向词法作用域,也就是外层调用者obj:
varobj={ birth:1990, getAge:function(){ varb=this.birth;//1990 varfn=()=>newDate().getFullYear()-this.birth;//this指向obj对象 returnfn(); } }; obj.getAge();//25如果使用箭头函数,以前的那种hack写法:
varthat=this;
就不再需要了。
由于this在箭头函数中已经按照词法作用域绑定了,所以,用call()或者apply()调用箭头函数时,无法对this进行绑定,即传入的第一个参数被忽略:
varobj={ birth:1990, getAge:function(year){ varb=this.birth;//1990 varfn=(y)=>y-this.birth;//this.birth仍是1990 returnfn.call({birth:2000},year); } }; obj.getAge(2015);//25练习
请使用箭头函数简化排序时传入的函数:
以上就是ES6标准ArrowFunction(箭头函数=>)的详细内容,更多关于js箭头函数的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。