23个超实用JS技巧 带有多个条件的if语句 把多个值放在一个数组中,然后调用数组的includes方法。 bad if(xabcxdefxghixjkl){ logic } better if(〔abc,def,ghi,jkl〕。includes(x)){ logic } 使用条件表达式简化iftrue。。。else bad lettest: if(x100){ }else{ } better lettestx10?true: 或者这样 lettestx10; console。log(test); 假值(undefined、null、0、false、NaN、空字符串)检查 当我们创建了新变量,有时候想要检查引用的变量是不是null或undefined或空字符串等假值。JavaScript确实有一个很好的快捷方式来实现这种检查逻辑或操作符() 会在左侧操作数为假值时返回右侧操作数 只有当左侧为:空字符串:或NaN0nullundefinedfalse 逻辑或操作符()会返回有右侧的值 bad if(test1!nulltest1!undefinedtest1!){ lettest2test1; } better lettest2test1; bad if(test1true)orif(test1!)orif(test1!null) better if(test1){ dosome }else{ doother } 注意:如果test1有值,将执行if之后的逻辑,这个操作符主要用于null,undefinded,空字符串检查。使用空值合并操作符?? 只有当左侧为nullundefined 空值合并操作符(??)会返回右侧的值 constbaz0??42; console。log(baz); expectedoutput:0 注意:与逻辑或操作符()不同,会在左侧操作数为假值时返回右侧操作数 只有当左侧为:空字符串:或NaN0nullundefined 逻辑或操作符()会返回有右侧的值 vara1; 输出1 console。log(a); null检查和默认赋值 lettest1 lettest2test1??; console。log(nullcheck,test2);输出空字符串 undefined检查和默认赋值 consttestundefined?? console。log(test); expectedoutput:default 比较后返回 bad functioncheckReturn(){ if(!(testundefined)){ }else{ returncallMe(test); } } better functioncheckReturn(){ returntest??callMe(test); } 使用可选链操作符?。 ?。也叫链判断运算符。它允许开发人员读取深度嵌套在对象链中的属性值,而不必验证每个引用。当引用为空时,表达式停止计算并返回undefined consttravelPlans{ destination:DC, monday:{ location:NationalMall, budget:200, }, }; bad constres travelPlans travelPlans。tuesday travelPlans。tuesday。location travelPlans。tuesday。location。 better 输出undefined constres1travelPlans?。tuesday?。location?。 用于多个条件判断的操作符 如果只在变量为true时才调用函数,可以使用操作符。 bad if(test1){ callMethod(); } better test1callMethod(); 当你在React中想要有条件地渲染某个组件时,这个与()短路写法比较有用。例如: {this。state。isLoading} switch简化 我们可以将条件保存在键值对象中,并根据条件来调用它们。 bad switch(data){ case1: test1(); case2: test2(); case3: test(); Andsoon。。。 } better vardata{ 1:test1, 2:test2, 3:test, }; 如果type在data中存在,则执行对应的函数 data〔type〕data〔type〕(); 默认参数值 bad functionadd(test1,test2){ if(test1undefined)test11; if(test2undefined)test22; returntest1test2; } better add(test11,test22)test1test2; add();output:3 条件查找简化 如果我们要基于不同的类型调用不同的方法,可以使用多个elseif语句或switch,但有没有比这更好的简化技巧呢?其实是前面的switch简化方式一样! bad if(typetest1){ test1(); }elseif(typetest2){ test2(); }elseif(typetest3){ test3(); }elseif(typetest4){ test4(); }else{ thrownewError(Invalidvaluetype); } better vartypes{ test1, test2, test3, test4, }; types〔type〕types〔type〕(); 对象属性赋值 lettest1a; lettest2b; bad letobj{test1:test1,test2:test2}; better letobj{test1,test2}; 解构赋值 bad consttest1this。data。test1; consttest2this。data。test2; consttest2this。data。test3; better const{test1,test2,test3}this。 模板字符串 如果你厌倦了使用将多个变量连接成一个字符串,那么这个简化技巧将让你不再头痛。 bad constwelcomeHitest1test2。; better constwelcomeHi{test1}{test2}; 跨行字符串 bad constdata abcabcabcabcabcabctesttest, better constdataabcabcabcabcabcabc testtest, indexOf的按位操作简化 在查找数组的某个值时,我们可以使用indexOf()方法。但有一种更好的方法,让我们来看一下这个例子。 bad if(arr。indexOf(item)1){ itemfound } if(arr。indexOf(item)1){ itemnotfound } better if(arr。indexOf(item)){ itemfound } if(!arr。indexOf(item)){ itemnotfound } 按位()运算符将返回true(1除外),反向操作只需要!。另外,也可以使用includes()函数。 if(arr。includes(item)){ trueiftheitemfound } 字符串转成数字 有一些内置的方法,例如parseInt和parseFloat可以用来将字符串转为数字。我们还可以简单地在字符串前提供一个一元运算符()来实现这一点。 bad lettotalparseInt(453); letaverageparseFloat(42。6); better lettotal453; letaverage42。6; 顺序执行promise 如果你有一堆异步或普通函数都返回promise,要求你一个接一个地执行,怎么办? asyncfunctiongetData(){ constpromises〔fetch(url1),fetch(url2),fetch(url3),fetch(url4)〕; for(constitemofpromises){ 打印出promise console。log(item); } better forawait(constitemofpromises){ 打印出请求的结果 console。log(item); } } 等待所有promise完成 Promise。allSettled()方法接受一组Promise实例作为参数,包装成一个新的Promise实例。只有等到所有这些参数实例都返回结果,不管是fulfilled还是rejected,包装实例才会结束 有时候,我们不关心异步请求的结果,只关心所有的请求有没有结束。这时,Promise。allSettled()方法就很有用 constpromises〔fetch(index。html),fetch(https:doesnotexist)〕; constresultsawaitPromise。allSettled(promises); 过滤出成功的请求 constsuccessfulPromisesresults。filter((p)p。statusfulfilled); 过滤出失败的请求,并输出原因 consterrorsresults 。filter((p)p。statusrejected) 。map((p)p。reason); 交换数组元素的位置 bad constswapWay(arr,i,j){ constnewArr〔。。。arr〕; lettempnewArr〔i〕; newArr〔i〕list〔j〕; newArr〔j〕 returnnewA }; ES6开始,从数组中的不同位置交换值变得容易多了 better constswapWay(arr,i,j){ constnewArr〔。。。arr〕; const〔newArr〔j〕,newArr〔i〕〕〔newArr〔i〕,newArr〔j〕〕; returnnewA }; 使用变量作为对象键 当你有一个字符串变量,并想将其用作对象中的键以设置一个值时可以用它 constobj{ b:b, }; obj〔property〕这是A; {b:b,name:这是A} console。log(obj); 带有范围的随机数生成器 有时你需要生成随机数,但希望这些数字在一定范围内,那就可以用这个工具。 functionrandomNumber(max1,min0){ if(minmax){ } returnMath。floor(Math。random()(maxmin)min); } 生成随机颜色 functiongetRandomColor(){ constcolorAngleMath。floor(Math。random()360); returnhsla({colorAngle},100,50,1); } 获取列表最后一项 其他语言里这个功能被做成了可以在数组上调用的方法或函数,但在JavaScript里面,你得自己做点工作。 letarray〔0,1,2,3,4,5,6,7〕; console。log(array。slice(1))〔7〕; console。log(array。slice(2))〔6,7〕; console。log(array。slice(3))〔5,6,7〕; functionlastItem(list){ if(Array。isArray(list)){ returnlist。slice(1)〔0〕; } if(listinstanceofSet){ returnArray。from(list)。slice(1)〔0〕; } if(listinstanceofMap){ returnArray。from(list。values())。slice(1)〔0〕; } } 图片懒加载 在懒加载的实现中,有两个关键的数值:一个是当前可视区域的高度,另一个是元素距离可视区域顶部的高度。 当前可视区域的高度,在和现代浏览器及IE9以上的浏览器中,可以用window。innerHeight属性获取。在低版本IE的标准模式中,可以用document。documentElement。clientHeight获取,这里我们兼容两种情况: constviewHeightwindow。innerHeightdocument。documentElement。clientH 而元素距离可视区域顶部的高度,我们这里选用getBoundingClientRect()方法来获取返回元素的大小及其相对于视口的位置。对此MDN给出了非常清晰的解释: 该方法的返回值是一个DOMRect对象,这个对象是由该元素的getClientRects()方法返回的一组矩形的集合,即:是与该元素相关的CSS边框集合。 DOMRect对象包含了一组用于描述边框的只读属性left、top、right和bottom,单位为像素。除了width和height外的属性都是相对于视口的左上角位置而言的。 LazyLoad 注意我们并没有为它引入真实的src 图片预加载 classPreLoadImage{ constructor(imgNode){ 获取真实的DOM节点 this。imgNodeimgN } 操作img节点的src属性 setSrc(imgUrl){ this。imgNode。srcimgU } } classProxyImage{ 占位图的url地址 staticLOADINGURL constructor(targetImage){ 目标Image,即PreLoadImage实例 this。targetImagetargetI } 该方法主要操作虚拟Image,完成加载 setSrc(targetUrl){ 真实img节点初始化时展示的是一个占位图 this。targetImage。setSrc(ProxyImage。LOADINGURL); 创建一个帮我们加载图片的虚拟Image实例 constvirtualImagenewImage(); 监听目标图片加载的情况,完成时再将DOM上的真实img节点的src属性设置为目标图片的url virtualImage。onload(){ this。targetImage。setSrc(targetUrl); }; 设置src属性,虚拟Image实例开始加载图片 virtualImage。srctargetU } } ProxyImage帮我们调度了预加载相关的工作,我们可以通过ProxyImage这个代理,实现对真实img节点的间接访问,并得到我们想要的效果。 https:www。ixiera。com