DefinearrowfunctionES6允许使用arrow=>definefunctionletv=100//箭头函数letf=a=>v;//等价于letf2=function(a){returnv}//等价于让f3=(a)=>{returnv}console.log(f());//100console.log(f2());//100console.log(f3());//100个箭头函数参数箭头函数中,用括号()表示参数部分//无参数leta1=()=>5;//等价于leta2=function(){return5}//带参数leta3=(num1,num2)=>num1+num2//等价于leta4=function(num1,num2){returnnum1+num2}如果箭头函数中的代码块是一个句子,大括号可以省略。如果箭头函数中的代码块不止一句话,需要用花括号括起来,使用return可以返回数据。大括号被解释为代码块。如果箭头函数返回的是对象,则必须在对象外加上括号,否则会报错//写法错误letb1=id=>{id:id,name:'东方无敌'}//报错//正确写法letid=1letb2=id=>({id,name:'东方不败'})console.log(b2());//id:undefined,name:'东方不败在上面的代码块中,箭头函数的参数是id,调用b2函数时没有传参,所以id是undefined,参数部分其实定义了一个letid;id未分配,因此未定义;在普通函数中,函数没有参数,函数内部也没有定义变量,内部变量会去查找变量,所以这里内部return的id指向外部全局变量idletid=1functionb3(){return{id,name:'东方寻败'}}console.log(b3());//id:1,name:'东方无敌'如果函数有参数,但调用函数时没有传参,则为undefined;//这里是一个Parameters,但是调用的时候没有传参数,所以id是undefinedfunctionb4(id){return{id,name:'东方秋白'}}console.log(b4());//id:undefined,name:'东方不败的函数参数部分其实是有作用域的,参数部分的id其实定义了一个letid。下面的例子可以说明://报错letid=1functionb5(id=id){return{id,name:'东方秋白'}}b5()这里的id其实就是letid=id,id是一个未声明的variable,assignid=id,报错//调用无参函数获取外层全局变量正确做法letid=1functionb5(val=id){return{val,name:'东方乞丐'}}console.log(b5());//id:1,name:'东方无敌'箭头函数返回值如果箭头函数只有一句话,没有返回值,可以在内容前面加void,不需要要写大括号,直接写内容就可以了letfooEmpty=()=>void'Noreturnvalue';console.log('无:',fooEmpty());//None:未定义的箭头函数有返回值letfooHave=()=>'hasreturnvalue';console.log('has:',fooHave());//has:hasreturnvaluearrowfunctionbracesletfoo=()=>{a:1}console.日志(富());//undefined上面的例子是一个特例,虽然可以运行,但是结果是错误的,因为花括号在箭头函数中被认为是代码块,这里的箭头函数不是{a:1}的对象返回,但执行表达式a:1。表达式执行后,操作结束,没有返回值正常的写法如下:letfoo2=()=>{return{a:1}}console.log(foo2());//{a:1}箭头函数解构赋值在参数部分传入对象,解构赋值letfoo3val={id:1,name:'孙悟空'}letfoo3=({id,name})=>console.log(`id:${id},name:${name}`);foo3(foo3val)//id:1,name:孙悟空解构赋值后,箭头函数可以让表达式更简洁,更多直觉的。比如这里封装了一个简单的实用函数,一行代码就完成了实用函数包constisEven=n=>n%2===0console.log(isEven(2));//trueconsole.log(isEven(3));//false简化了回调函数普通函数的写法letfil=[1,2,3].filter(function(x){returnx==2})console.log(fil);//[2]写箭头函数,一行完成letfil2=[1,2,3].filter(el=>el==2)console.log(fil2);//[2]箭头函数的注意点1.箭头函数没有this对象2.不能作为构造函数使用。也就是说箭头函数不能使用new命令,否则会报错3.arguments对象不能使用,函数体中不存在。4、不能使用yield命令,因为箭头函数不能作为生成器函数使用。箭头函数使this始终指向函数定义生效的对象。箭头函数this指向什么时候使用箭头函数在注意点中,最需要注意的就是this指向的问题。下面用一个例子来说明箭头函数this的指向问题。functionarrows(){console.log('name:',this.name);//中国工艺美术史setTimeout(()=>{console.log('name:',this.name);//中国工艺美术史},100)setTimeout(function(){console.log('姓名:',this.name);//美术概论},100)}varname='美术概论'arrows.call({name:'中国工艺美术史'})//name:中国工艺美术史调用函数:第一个参数表示:你希望this指向的对象(obj);第二个参数表示:实际传入的参数。如果call的第一个参数没有传值,或者值为null,那么箭头在中间,this指向第一个参数传入的window,而this指向obj对象。第一个定时器setTimeout使用箭头函数。在普通函数中,setTimeout指向的是window,但是这里setTimeout使用了一个箭头函数,导致计时指针指向调用函数定义生效的对象,所以这里打印的是中国工艺美术史,而不是最外层的全局变量。第二个定时器setTimeout没有使用箭头函数,即使使用了call()方法,函数内部的定时器仍然指向window。箭头函数没有自己的this,所以内部的this就是外层代码块的this。正是因为没有this,才不能作为构造函数使用。箭头函数没有自己的this,而是引用了外面的this。下面是Babel转箭头函数生成的ES5代码,可以很清楚的说明this的方向。//ES6functionfoo(){setTimeout(()=>{console.log('id:',this.id);},100);}//ES5functionfoo(){var_this=this;setTimeout(function(){console.log('id:',_this.id);},100);}箭头函数不适用的场合1:在对象中定义箭头函数letcat={level:9,jumps:()=>{this.level}}在这个例子中,cat.jumps()是一个箭头函数,这是错误的。如果cat.jumps()是一个普通函数,则方法内部的this指向cat。如果调用cat.jumps()是一个箭头函数,则this指向全局对象。因为对象不构成单独的作用域,所以jumps箭头函数定义的作用域是全局作用域。2:当需要动态this时,上面的箭头函数letbutton=document.getElementById('news')button.addEventListener('click',()=>{this.classList.toggle('on')})不应该在使用代码运行时,点击按钮会报错,因为按钮监听函数是一个箭头函数,导致内部的this是一个全局对象。如果改成普通函数,this会动态指向被点击的按钮对象。另外,如果函数体比较复杂,行数多,或者函数内部的读写操作比较多,不只是计算值,这时候不应该使用箭头函数,而是使用普通函数,这样可以提高代码的灵活性。可读性。案例源码:https://gitee.com/wang_fan_w/es6-science-institute如果您觉得本文对您有帮助,请点亮star
