一段干净的代码,您可以非常轻松地阅读、重用和重构。编写干净的代码非常重要,因为在我们的日常工作中,您不仅仅是在为自己编写代码。事实上,你还需要考虑一群需要理解、编辑和构建你的代码的同事。1.为变量使用有意义的名称变量名称应该是描述性的和有意义的。JavaScript变量应该以驼峰命名。//不要?constfoo="JDoe@example.com";constbar="John";constage=23;constqux=true;//Do?constemail="John@example.com";constfirstName="John";consstage=23;constisActive=true布尔变量通常需要回答特定的问题,例如:isActivedidSubscribehasLinkedAccount(1)避免添加不必要的上下文当对象或类已经包含上下文的命名时,不要在变量名中添加多余的上下文.//不要?constuser={userId:"296e2589-7b33-400a-b762-007b730c8e6d",userEmail:"JDoe@example.com",userFirstName:"John",userLastName:"Doe",userAge:23,};user.userId;//Do?constuser={id:"296e2589-7b33-400a-b762-007b730c8e6d",email:"JDoe@example.com",firstName:"John",lastName:"Doe",age:23,};(2)避免对值进行硬编码确保声明有意义且可搜索的常量,而不是直接插入常量值。全局常量可以以SCREAMING_SNAKE_CASE风格命名。//不要?setTimeout(clearSessionData,900000);//Do?constSESSION_DURATION_MS=15*60*1000;setTimeout(clearSessionData,SESSION_DURATION_MS);2.为函数使用有意义的名字函数名需要描述函数的实际功能,即使长一点也没关系。函数名通常使用动词,但返回布尔值的函数可能是个例外——它可以采用是或否问题的形式,函数名也应该采用驼峰式大小写。//不要?functiontoggle(){//...}functionagreed(user){//...}//Do?functiontoggleThemeSwitcher(){//...}functiondidAgreeToAllTerms(user){//...}(1)使用默认参数默认参数比&&||更简洁或者在函数体内使用额外的条件语句。//Don't?functionprintAllFilesInDirectory(dir){constdirdirectory=dir||"./";//...}//Do?functionprintAllFilesInDirectory(dir="./"){//...}(2)限制参数的数量尽管这条规则可能有争议,但函数最好有3个或更少的参数。如果参数较多,可能是以下两种情况之一:函数做的事情太多,应该拆分。传递给函数的数据以某种方式相关,可以作为专门的数据结构传递。//Don't?functionsendPushNotification(title,message,image,isSilent,delayMs){//...}sendPushNotification("NewMessage","...","http://...",false,1000);//Do?functionsendPushNotification({title,message,image,isSilent,delayMs}){//...}constnotificationConfig={title:"NewMessage",message:"...",image:"http://...",isSilent:false,delayMs:1000,};sendPushNotification(notificationConfig);(3)避免在一个函数中做太多事情一个函数应该一次只做一件事,这有助于减少大小功能和复杂性,使测试、调试和重构更容易。/不要?functionpingUsers(users){users.forEach((user)=>{constuserRecord=database.lookup(user);if(!userRecord.isActive()){ping(user);}});}//Do?functionpingInactiveUsers(users){users.filter(!isUserActive).forEach(ping);}functionisUserActive(user){constuserRecord=database.lookup(user);returnuserRecord.isActive();}(4)避免使用布尔标志带有布尔标志的参数作为函数的参数意味着可以简化函数。//不要?functioncreateFile(name,isPublic){if(isPublic){fs.create(`./public/${name}`);}else{fs.create(name);}}//做?functioncreateFile(name){fs.create(name);}functioncreatePublicFile(name){createFile(`./public/${name}`);}(5)避免写重复代码如果你写重复代码,每次有一个逻辑变化,你需要改变多个位置。//不要?functionrenderCarsList(cars){cars.forEach((car)=>{constprice=car.getPrice();constmake=car.getMake();constbrand=car.getBrand();constnbOfDoors=car.getNbOfDoors();render({price,make,brand,nbOfDoors});});}functionrenderMotorcyclesList(motorcycles){motorcycles.forEach((motorcycle)=>{constprice=motorcycle.getPrice();constmake=motorcycle.getMake();constbrand=motorcycle.getBrand();constseatHeight=motorcycle.getSeatHeight();render({price,make,brand,nbOfDoors});});}//Do?functionrenderVehiclesList(vehicles){vehicles.forEach((vehicle)=>{constprice=vehicle.getPrice();constmake=vehicle.getMake();constbrand=vehicle.getBrand();constdata={price,make,brand};switch(vehicle.type){case"car":data.nbOfDoors=vehicle.getNbOfDoors();break;case"motorcycle":data.seatHeight=vehicle.getSeatHeight();break;}render(data);});}(6)为了避免JavaScript中的副作用,你应该更喜欢函数式模式而不是命令式模式。换句话说,我们应该在大多数时候保持函数的纯净。副作用会修改共享状态和资源,从而导致一些奇怪的问题。所有的副作用都应该集中管理。例如,如果您需要更改全局变量或修改文件,您可以编写一个util来执行此操作。//Don't?letdate="21-8-2021";functionssplitIntoDayMonthYear(){datedate=date.split("-");}splitIntoDayMonthYear();//另一个函数可能期望日期为stringconsole.log(date);//['21','8','2021'];//Do?函数splitIntoDayMonthYear(date){returndate.split("-");}constdate="21-8-2021";constnewDate=splitIntoDayMonthYear(date);//原始vlaueisintactconsole.log(date);//'21-8-2021';console.log(newDate);//['21','8','2021'];此外,如果您将可变值传递给函数,您应该只克隆一个新值而不是改变它。//Don't?functionenrollStudentInCourse(course,student){course.push({student,enrollmentDate:Date.now()});}//Do?functionenrollStudentInCourse(course,student){return[...course,{student,enrollmentDate:Date.now()}];}3.条件语句(1)使用非否定条件//Don't?functionisUserNotVerified(user){//...}if(!isUserNotVerified(user)){//...}//Do?functionisUserVerified(user){//...}if(isUserVerified(user)){//...}(2)尽量使用速记//不要?if(isActive===true){//...}if(firstName!==""&&firstName!==null&&firstName!==undefined){//...}constisUserEligible=user.isVerified()&&user.didSubscribe()?true:false;//Do?if(isActive){//...}if(!!firstName){//...}constisUserEligible=user.isVerified()&&user.didSubscribe();(3)避免太多分支和提前返回会使你的代码线性化,更具可读性和更简单。//不要?functionaddUserService(db,user){if(!db){if(!db.isConnected()){if(!user){returndb.insert("users",user);}else{thrownewError("Nouser");}}else{thrownewError("Nodatabaseconnection");}}else{thrownewError("Nodatabase");}}//Do?functionaddUserService(db,user){if(!db)thrownewError("Nodatabase");if(!db.isConnected())thrownewError("Nodatabaseconnection");if(!user)thrownewError("Nouser");returndb.insert("users",user);}(4)使用地图首先不是switch语句可以降低复杂度,提高性能。//不要?constgetColorByStatus=(status)=>{switch(status){case"success":return"green";case"failure":return"red";case"warning":return"yellow";case"loading":default:return"blue";}};//Do?conststatusColors={成功:"green",失败:"red",warning:"yellow",loading:"blue",};constgetColorByStatus=(status)=>statusColors[status]||"blue";(5)使用可选链接constuser={email:"JDoe@example.com",billing:{iban:"...",swift:"..。计费&&user.billing.address&&user.billing.address.street)||"N/A";conststate=(user&&user.billing&&user.billing.address&&user.billing.address.state)||";N/A";//Do?constemail=user?.email???"N/A";conststreet=user?.billing?.address?.street??"N/A";conststreet=user?.billing?.address?.state??"N/A";4.并发避免回调:回调容易混淆,会导致代码嵌套太深,使用Promise代替回调//Don't?getUser(function(err,user){getProfile(user,function(err,profile){getAccount(profile,function(err,account){getReports(account,function(err,reports){sendStatistics(reports,function(err){console.error(err);});});});});});//Do?getUser().then(getProfile).then(getAccount).then(getReports).then(sendStatistics).catch((err)=>console.error(err));//或使用Async/Await??asyncfunctionsendUserStatistics(){try{constuser=awaitgetUser();constprofile=awaitgetProfile(user);constaccount=awaitgetAccount(profile);constreports=awaitgetReports(account);returnsendStatistics(reports);}catch(e){console.error(err);}}5.错误处理处理抛出的错误和拒绝的promise/Don't?try{//Possibleerronouscode}catch(e){console.log(e);}//Do?try{//Possibleerronouscode}catch(e){//Followthemostapplicable(orall)://1-Moresuitablethanconsole.logconsole.error(e);//2-NotifyuserifapplicablealertUserOfError(e);//3-ReporttoserverreportErrorToServer(e);//4-UseacustomerrorhandlerthrownewCustomError(e);}6.注释(1)只注释业务逻辑可读的代码避免过多注释,因此,你应该只注释复杂的逻辑//Don't?functiongenerateHash(str){//Hashvariablelethash=0;//Getthelengthofthestringletlength=str.length;//Ifthestringisemptyreturnif(!length){returnhash;}//遍历字符串中的每个字符for(leti=0;i
