本文的目的在于帮助大家更加熟练的运用 JavaScript 语言来进行开发工作。
带有多个条件的 if 语句
把多个值放在一个数组中,然后调用数组的 includes 方法。
//bad??if(x===”abc”||x===”def”||x===”ghi”||x===”jkl”){//logic}//better??if([“abc”,”def”,”ghi”,”jkl”].includes(x)){//logic}使用条件表达式简化 if true…else//bad??lettest:boolean;if(x>100){test=true;}else{test=false;}//better??lettest=x>10?true:false;//或者这样lettest=x>10;console.log(test);假值(undefined、null、0、false、NaN、空字符串)检查
当我们创建了新变量,有时候想要检查引用的变量是不是null 或 undefined或空字符串 等假值。JavaScript 确实有一个很好的快捷方式来实现这种检查-逻辑或操作符(||)
||会在左侧操作数为假值时返回右侧操作数
只有当左侧为:
空字符串: ”或“NaN0nullundefinedfalse
逻辑或操作符(||) 会返回有右侧的值
//bad??if(test1!==null||test1!==undefined||test1!==””){lettest2=test1;}//better??lettest2=test1||””;//bad??if(test1===true)orif(test1!==””)orif(test1!==null)//better??if(test1){//dosome}else{//doother}
注意:如果 test1 有值,将执行 if 之后的逻辑,这个操作符主要用于 null,undefinded,空字符串 检查。
使用空值合并操作符-??
只有当左侧为
nullundefined
空值合并操作符(??) 会返回右侧的值
constbaz=0??42;console.log(baz);//expectedoutput:0
注意:与逻辑或操作符(||)不同,||会在左侧操作数为假值时返回右侧操作数
只有当左侧为:
空字符串: ”或“NaN0nullundefined
逻辑或操作符(||) 会返回有右侧的值
vara=””||1;//输出1console.log(a);null 检查和默认赋值lettest1=null;lettest2=test1??””;console.log(“nullcheck”,test2);//输出空字符串””undefined 检查和默认赋值consttest=undefined??”default”;console.log(test);//expectedoutput:”default”比较后返回//bad??lettest;functioncheckReturn(){if(!(test===undefined)){returntest;}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.href;//better??//输出undefinedconstres1=travelPlans?.tuesday?.location?.href;用于多个条件判断的 && 操作符
如果只在变量为 true 时才调用函数,可以使用 && 操作符。
//bad??if(test1){callMethod();}//better??test1&&callMethod();
当你在 React 中想要有条件地渲染某个组件时,这个与 (&&)短路写法比较有用。例如:
<div> {this.state.isLoading && <Loading />} </div>switch 简化
我们可以将条件保存在键值对象中,并根据条件来调用它们。
//bad??switch(data){case1:test1();break;case2:test2();break;case3:test();break;//Andsoon…}//better??vardata={1:test1,2:test2,3:test,};//如果type在data中存在,则执行对应的函数data[type]&&data[type]();默认参数值//bad??functionadd(test1,test2){if(test1===undefined)test1=1;if(test2===undefined)test2=2;returntest1 test2;}//better??add=(test1=1,test2=2)=>test1 test2;add();//output:3条件查找简化
如果我们要基于不同的类型调用不同的方法,可以使用多个 else if 语句或 switch,但有没有比这更好的简化技巧呢?其实是前面的 switch 简化方式一样!
//bad??if(type===”test1″){test1();}elseif(type===”test2″){test2();}elseif(type===”test3″){test3();}elseif(type===”test4″){test4();}else{thrownewError(“Invalidvalue” type);}//better??vartypes={test1,test2,test3,test4,};types[type]&&types[type]();对象属性赋值lettest1=”a”;lettest2=”b”;//bad??letobj={test1:test1,test2:test2};//better??letobj={test1,test2};解构赋值//bad??consttest1=this.data.test1;consttest2=this.data.test2;consttest2=this.data.test3;//better??const{test1,test2,test3}=this.data;模板字符串
如果你厌倦了使用 将多个变量连接成一个字符串,那么这个简化技巧将让你不再头痛。
//bad??constwelcome=”Hi” test1 “” test2 “.”;//better??constwelcome=`Hi${test1}${test2}`;跨行字符串//bad??constdata=”abcabcabcabcabcabc\n\t” “testtest,testtesttesttest\n\t”;//better??constdata=`abcabcabcabcabcabctesttest,testtesttesttest`;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??lettotal=parseInt(“453”);letaverage=parseFloat(“42.6”);//better??lettotal= “453”;letaverage= “42.6”;顺序执行 promise
如果你有一堆异步或普通函数都返回 promise,要求你一个接一个地执行,怎么办?
asyncfunctiongetData(){constpromises=[fetch(“url1”),fetch(“url2”),fetch(“url3”),fetch(“url4”)];for(constitemofpromises){//打印出promiseconsole.log(item);}//better??forawait(constitemofpromises){//打印出请求的结果console.log(item);}}等待所有 promise 完成
Promise.allSettled()方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只有等到所有这些参数实例都返回结果,不管是 fulfilled 还是 rejected,包装实例才会结束
有时候,我们不关心异步请求的结果,只关心所有的请求有没有结束。这时,Promise.allSettled()方法就很有用
const promises = [fetch(“index.html”), fetch(“https://does-not-exist/”)];const results = await Promise.allSettled(promises);// 过滤出成功的请求const successfulPromises = results.filter((p) => p.status === “fulfilled”);// 过滤出失败的请求,并输出原因const errors = results .filter((p) => p.status === “rejected”) .map((p) => p.reason);交换数组元素的位置//bad??constswapWay=(arr,i,j)=>{constnewArr=[…arr];lettemp=newArr[i];newArr[i]=list[j];newArr[j]=temp;returnnewArr;};
ES6 开始,从数组中的不同位置交换值变得容易多了
// better ??const swapWay = (arr, i, j) => { const newArr = […arr]; const [newArr[j],newArr[i]] = [newArr[i],newArr[j]]; return newArr;};使用变量作为对象键
当你有一个字符串变量,并想将其用作对象中的键以设置一个值时可以用它
letproperty=”a”;constobj={b:”b”,};property=”name”;obj[property]=”这是A”;//{b:”b”,name:”这是A”}console.log(obj);带有范围的随机数生成器
有时你需要生成随机数,但希望这些数字在一定范围内,那就可以用这个工具。
functionrandomNumber(max=1,min=0){if(min>=max){returnmax;}returnMath.floor(Math.random()*(max-min) min);}生成随机颜色function getRandomColor() { const colorAngle = Math.floor(Math.random() * 360); return `hsla(${colorAngle},100%,50%,1)`;}获取列表最后一项
其他语言里这个功能被做成了可以在数组上调用的方法或函数,但在 JavaScript 里面,你得自己做点工作。
let array = [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 获取,这里我们兼容两种情况:
constviewHeight=window.innerHeight||document.documentElement.clientHeight;
而元素距离可视区域顶部的高度,我们这里选用 getBoundingClientRect() 方法来获取返回元素的大小及其相对于视口的位置。对此 MDN 给出了非常清晰的解释:
该方法的返回值是一个 DOMRect 对象,这个对象是由该元素的 getClientRects() 方法返回的一组矩形的集合, 即:是与该元素相关的 CSS 边框集合 。
DOMRect 对象包含了一组用于描述边框的只读属性——left、top、right 和 bottom,单位为像素。除了 width 和 height 外的属性都是相对于视口的左上角位置而言的。
ProxyImage 帮我们调度了预加载相关的工作,我们可以通过 ProxyImage 这个代理,实现对真实 img 节点的间接访问,并得到我们想要的效果。
参考文档前端性能优化原理与实践[1]JavaScript 设计模式核??原理与应??实践[2]你应该了解的 25 个 JS 技巧[3]参考资料[1]
https://juejin.cn/book/6844733750048210957/section/6844733750119514126: https://juejin.cn/book/6844733750048210957/section/6844733750119514126
[2]
https://juejin.cn/book/6844733790204461070/section/6844733790275780621: https://juejin.cn/book/6844733790204461070/section/6844733790275780621
[3]
https://mp.weixin.qq.com/s/IFmzGyz3MWOYj80qrq1Uig: https://link.juejin.cn?target=https://mp.weixin.qq.com/s/IFmzGyz3MWOYj80qrq1Uig
最后
如果你觉得这篇内容对你挺有启发,我想邀请你帮我三个小忙: