JavaScript语言在不断的发布一些新的特性,感觉就像天上掉下来的节奏。本文收集整理了它的一些高级概念和用法,看看你是否都了解了?这样写的代码是不是更优雅?1.闭包闭包是Javascript中的一项重要技术,内层函数始终可以访问其外层函数的变量和参数,即使在外层函数返回之后。我们使用闭包来保护我们不想暴露给外部范围的数据。//增加计数器//1.全局变量,变量会被不小心修改letcounter=0;functionincreaseCounter(){counter++;}//2.局部变量,每次调用都重置为0functionincreaseCounter(){letcounter=0;计数器++;}//3。闭包函数满足要求constincreaseCounter=(function(){letcounter=0;returnfunction(){counter=counter+1;console.log(counter);};})();2。当函数绑定的上下文丢失时,this无法判断,可以通过函数绑定来解决。//1.不符合预期,得到了undefinedletbook={title:'LearnJavaScript',printTitle(){console.log(`Book'stitle:${this.title}`);}}setTimeout(book.printTitle,1000);//Book'stitle:undefined//2.使用函数绑定,正如预期的那样}}让printTitle=book.printTitle.bind(book);setTimeout(printTitle,1000);//书名:JavaScript3.使用命名空间使用命名空间可以防止代码冲突。//1.move和jump函数在animal命名空间中,需要通过animal.move()调用letanimal={move:()=>{console.log('Move!');},跳跃:()=>{console.log('跳跃!');}};//2.在实际项目中,命名空间可以这样使用if(typeofAPP==="undefined"){APP={};APP.ANIMAL={};}APP.ANIMAL.move=()=>{console.log('Move');};APP.ANIMAL.jump=()=>{console.log('Jump');};APP.ANIMAL.move();//MoveAPP.ANIMAL.jump();//跳转4。确定属性是否存在使用in关键字确定对象中是否存在属性。constperson={id:"123",name:"张三"}console.debug("id"inperson)//trueconsole.debug("age"inperson)//false5.解构赋值使用解构赋值表达式,可以从对象和数组中取出属性和值,赋值给其他变量,非常方便。const{address:addressLine}={address:"长安街20号",postcode:"518118"};console.warn(addressLine);//长安街20号const[first,second]=[1,2,3,4]console.warn(first,second)//12//动态解构constextractKey="postcode"const{[extractKey]:youbian}={address:"长安街20号",postcode:"518118"};console.log(youbian)//5181186.遍历对象属性使用Object.entries遍历对象属性和值。constdata={address:"长安街20号",postcode:"518118"};Object.entries(data).forEach(([key,value])=>{if(["address","postcode"].includes(key)){console.log('key:',key,'value:',value)}})//输出结果如下key:地址value:长安20号Avenuekey:postcodevalue:5181187.filter数组使用过滤器和一些数组来过滤数组。constfruits=["apple",null,"mongo",undefined,""]constfiltered=fruits.filter(Boolean)console.debug(filtered)//(2)["apple","mongo"]constany=fruits.some(Boolean)console.log(any)//true8。消除重复值constfruits=["apple",null,"mongo","apple",""]constunique=[...newSet(fruits)]console.debug(uniqued)//(4)[“苹果”,空,“蒙戈”,“”]9。使用Array.isArray代替typeof判断是否为数组。constfruits=["apple",null,"mongo","apple",""]console.debug(typeoffruits)//objectconsole.error(Array.isArray(fruits))//true10。转换数字和字符串consttext="12345"console.debug("text:",+text,"typeof:",typeof(+text))//text:12345typeof:numberconstnum=123456console.debug("number:",num+"","typeof:",typeof(num+""))//number:123456typeof:string11.转换为布尔值使用!!运算符将其他类型转换为布尔类型。console.log(!!null,typeof(!!null))//false,booleanconsole.log(!!"",typeof(!!"))//false,booleanconsole.log(!!undefined,typeof(!!undefined))//false,booleanconsole.log(!!null,typeof(!!null))//false,booleanconsole.log(!!true,typeof(!!true))//true,booleanconsole.log(!!false,typeof(!!false))//false,booleanconsole.log(!!{id:"",name:""},typeof(!!{id:"",name:""}))//真,布尔值12。可选链可选链?是一种访问嵌套对象属性的安全方法,可避免在对象或属性不可用时引发异常。由于JavaScript不是一种类型化语言,这个特性仍然很有用。//如果不使用可选链接,会抛出异常constcontactInfos={address:"长安街20号"};console.warn(contactInfos.user.phoneNumber)//上面的语句会报错报错:Cannotreadpropertiesofundefined(reading'phoneNumber')//useoptionallink,willprintundefinedconstcontactInfos={address:"长安街20号"};console.warn(contactInfos.user?.phoneNumber)//未定义13.Combineoperatorandcombineoperator对于两个问号??,对于这个运算符连接的两个参数,如果第一个参数不为null或undefined,则返回第一个参数,否则返回第二个参数。constcontactInfos={address:"长安街20号"};console.warn(contactInfos.user?.phoneNumber??"")//""constcontactInfos={address:"长安街20号'anStreet",addressNumber:0};console.warn(contactInfos.addressNumber||undefined)//undefinedconsole.warn(contactInfos.addressNumber??undefined)//014.使用...扩展语法有条件地添加属性,您可以只有当某个条件为真时,才能给对象添加一个属性。constmoreInfos={信息:“请开车到那里。”}return{address:"长安街20号",postcode:"518118",...(moreInfos!==undefined&&{moreInfos})//只有当moreInfos不是moreInfos属性时才添加itisundefined}15.异步调用异常捕获下面的写法使得处理异步调用异常的代码更加简洁。常量结果=等待getPosts()。catch((err)=>{return{type:"error",message:err.message}});安慰。warn(results)//{type:"error",message:"cannotgetpostsfromthisendpoint"}16.弱引用MapWeakmap不同于Map,它的key必须是引用对象,而不是基本类型,如果没有对key对象的引用,该对象就会从Map中移出并内存remove。constvideoSegments=newWeakMap()letoptions={id:"1234",timeStart:1653831957378,size:10000}constsegment={data:newUint8Array(200)}videoSegments.set(options,segment)console.warn(videoSegments.get(options))//{data:newUint8Array(200)}//当options赋值为null时,对象会被移除并回收options=nullconsole.warn(videoSegments.has(options))//false,`options`键对象从WeakMap17中删除。ReflectReflect是一个全局对象,它为元编程提供了一些有用的静态方法。constperson={name:'Bob',[Symbol('email')]:'bob@evil.com'};Reflect.get(person,'name');//=BobReflect.has(person,'email'');//=trueReflect.has(person,'phone');//=falseReflect.getPrototypeOf(person);//={构造函数...}Reflect.getOwnPropertyDescriptor(person,'name');//={value:'Bob',writable:true,enumerable:true,configurable:true}Reflect.ownKeys(person);//名字,Symbol(email)Reflect.defineProperty(person,'phone',{writable:true});Reflect.has(person,'phone');//=trueReflect.set(person,'phone','123456789');Reflect.deleteProperty(person,'phone');Reflect.has(person,'phone');//=false18。Currying柯里化(Currying)是一种关于函数的高级技术,指的是将一个函数从可调用的f(a,b,c)转换为可调用的f(a)(b)(c)。柯里化不调用函数,它只是转换函数。//完成银行转账交易功能,balance+transferamount-feeconsttransaction=(fee,balance,amount)=>(balance+amout-fee;);//简单咖喱函数constcurry=(fn,...args)=>((..._arg)=>(fn(...args,..._arg)));//重用交易函数的交易免手续费函数constfreeTransaction=curry(transaction,0);免费交易(10、90);//=10019.Composition组合是一种将一个函数的结果传递给下一个函数的技术,下一个函数又传递给下一个函数,依此类推......直到执行最终函数并计算出一些结果.函数组合可以由任意数量的函数组成。//f和g都是函数,x是它们之间的“管道”值varcompose=function(f,g){returnfunction(x){returnf(g(x));};};vartoUpperCase=function(x){returnx.toUpperCase();};varexclaim=function(x){returnx+'!';};varshout=compose(exclaim,toUpperCase);shout("派小丑进来");//=>"SENDINTHECLOWNS!"//组合函数constcompose=(...fns)=>x=>fns.reduce((y,f)=>f(y),x);//原函数constaddFee=amount=>amount+2;constaddDiscount=amount=>amount-5;//函数组合constcomposition=compose(addFee,addDiscount)(100);console.log(composition)//97