如何写出优雅耐看的JavaScript代码_第1页
如何写出优雅耐看的JavaScript代码_第2页
如何写出优雅耐看的JavaScript代码_第3页
如何写出优雅耐看的JavaScript代码_第4页
如何写出优雅耐看的JavaScript代码_第5页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

在我们平时的工作开发中,大多数都是大人协同开发的公共项目;在我们平时开

发中代码codeing的时候我们考虑代码的可读性、复用性和扩展性。

干净的代码,既在质量上较为可靠,也为后期维护、升级奠定了良好基础。

我们从以下几个方面进行探讨:

变量

I、变量命名

一般我们在定义变量是要使用有意义的词汇命令,要做到见面知义

//badcodec。八允yyyymmdstr=inaokviek\t().fori^at(,YYYY/MM/DDt);//betteK'codecoi^st

cuirrei^tDate=momer\t().format(rYYYY/MM/PP/);

2、可描述

通过一个变量生成了一个新变量,也需要为这个新变量命名,也就是说每个变量

当你看到他第一眼你就知道他是干什么的。

//bad.stADDRESS='OMInfiniteLoop,Cupertino<?5(914,;const

CrTYN【P_CODE_REGEX=

/Ar,\\J+L\\\sJ+(.+?)\s*(\d{5})?申/;saveCit9Z3Code(ADDRESS.match(aTY_Z/P_CODE_REG

EX)[1]>ADDRESS.MntcMaTYN/P_CODE_REGEX)[2]);

//bettercodecoimtADDRESS='OMInfiniteLoop,Cupertino95'。工4,;const

CrTYNIP_CODE_REGEX=/入[入,\\J+L\\\sJ+(.+?)\s*(V{5})?$/;CMSt[,city,zipCode]=

ADDRESS.3atck(67TY_Z/P_CODE_REGEX)||[];save.CityZipCod.e(city,zipCode);

3、形参命名

在for、forEach、m叩的循环中我们在命名时要直接

//bad.codeco^stlocations=['Austin,'NewYorkS'Sa^Francisco1];

locatio^.i^ap((l)=>{

doStuff();

doSo^v\eOtkerStuff();

//...

//...

//…

//需要看其他代码才能确定W是干什么的。

dispatch(l);

});

//bettercodeco^stlocation=pAustiW,'NewYorkS'SaiaFrancisco'];

locatio^s.forEach((locatioio)=>{

doStuff();

doSokv\eOtherStuff();

//…

//...

//...

dispatch(locatioi^)

!);

4、避免无意义的前缀

例如我们只创建一个对象是,没有必要再把每个对象的属性上再加上对象名

//bad.codeco八stcar={

carMake:^oiada',

carModel:Accord1,

carColor.

};

fiAnctioK\paii^tCa^car){

cav.carColor-'Red';

)

//tettercodec。八stcar={

hakc」H。八

w<odd:Accord1,

color.'Blue'

};

fanotionpaii^tCa^(car){

car.color=&ed';

)

5、默认值

//badcodefix八ctio八createMicrobrewery(^ai^e){

constferewery/\/ame=name||'HipsterBrewCo.1;

//...

)

//bettercodefuMtioi^createMicrobrewery(^.akv\e='HipsterBrewCo.1){

//...

)

函数

1、参数

一般参数多的话要使用ES6的解构传参的方式

//badcodefuMtioiacreateMe^u(title,body,buttoiaText,cancellable){

//...

)

//bettercodefunctioncre〃teMc八〃({title,body,buttov^Text,cancellable}){

//...

)

//bettercodecre〃teMe八〃({

title:Fool

body:'Bar1,

butto^Text:'Boz>

cancellable:true

});

2、单一化处理

一个方法里面最好只做一件事,不要过多的处理,这样代码的可读性非常高

//bad.codefuMtioia{

八ts.forE〃火(d电峭=>{

constclieiatRecord=database.lookup(clie^)

if(cliei^tRecord.isActiveO){

CK/UU7(C他叫;

)

1);

)

//tettercodefuMtiotae^ailActiveClieirits(clieiats){

clients

filter(kActiveClient)

.forEach(ei^air);

jfuMtioni$ActiveClient(clie^t){

constclientRecord=database.lookup(clie^t);

returndientReco".isActive。;

]

3、对象设置默认属性

//badcodec。八sti^eiauConfig={

title:nullj

body:依匕

buttonText:nullj

cancellable:true

J;fui^ction.weateMeNA(cocfig){

coiafig.title=config.title||'Foo';

config.body-coiafig.body||'Bar1;

1

co八fig.biAttonText=coiafig.battoi^Text||'Baz;

co八fig.ca八cellablc=c。八fig.ca八callable/==imdcfined?ccmfig.ca八cellablc:true;

"catcMc八〃(3"uCo八饱);

//bettercodec。八允八饱={

iMe「O〃ey,

///body1key缺失

b〃tt。八Text:5e八d,

caiacellable:true

};

FL(八ctio八creatcMc八认(co八fig){

config=O勿ect.assig八({

title:'F。。,

body:

buttoiaText:'Baz1j

cancellable,true

力config);

//config就变成了:{土"也:"。以e叫body:butto八Text:"Se八d",cancellable:true}

//...

)

八(4(w\e八"Co八饱);

4、避免副作用

函数接收一个值返回一个新值,除此之外的行为我们都称之为副作用,比如修改

全局变量、对文件进行10操作等。

当函数确实需要副作用时,比如对文件进行10操作时,请不要用多个函数/类

进行文件操作,有且仅用一个函数/类来处理。也就是说副作用需要在唯一的地

方处理。

副作用的三大天坑:随意修改可变数据类型、随意分享没有数据结构的状态、没

有在统一地方处理副作用。

//badcode//全局变量被一个函数引用//现在这个变量从字符串变成了数组,如果有其他的函数引用,

会发生无法预见的错促vavname='Rga八splitt^toFirstAi^dLastNai^eC){

八4MAe=Mi^esplitC');

}splitln.toFirstAiadLastNakv\e();co^ole.log(k\ai^e);//^McPermottJ;

//bettercodevar八口侬。=’RganMcDer做。tt';varn=

FIA八ctio八splitli^toFirstAiadLa^tNai^e(i^ame){

returnnai^esplitC,);

,,,

cok\$ole.log(nakv\e);//'Rga八McDerkv\ott;cok\sole.log(MwMakv\e);//McDeri^ott]j

在JavaScript中,基本类型通过赋值传递,对象和数组通过引用传递。以引用

传递为例:

假如我们写一个购物车,通过"山teMToCnrtO方法添加商品到购物车,修改购物

车数组。此时调用purchase。方法购买,由于引用传递,获取的购物车数组正好是最

新的数据。

看起来没问题对不对?

如果当用户点击购买时,网络出现故障,purchase。方法一直在重复调用,与此

同时用户又添加了新的商品,这时网络又恢复了。那么仆rckaseO方法获取到购物

车数组就是错误的。

为了避免这种问题,我们需要在每次新增商品时,克隆购物乍数组并返回新的数组。

//badcodeco^taddltewCToCart-(cart,混出)=>{

cart.push({date:D〃2©mow。});

);

//bettercodec。八staddltew^VoCart-(cart,/tern)=>{

return[...cavt,date:Date.MW()}]

);

5、全局方法

在JavaScript中,永远不要污染全局,会在生产环境中产生难以预料的bug。

举个例子,比如你在A"叫"。切均pe上新增一个"f方法来判断两个数组的不同。

而你同事也打算做类似的事情,不过他的W肝方法是用来判断两个数组首位元素

的不同。很明显你们方法会产生冲突,遇到这类问题我们可以用ES2015/ES6的

语法来对Army进行扩展。

//badcodeAtotype.diff=fcmctio八diff(coi^parisoioA^ay){

cov\stkash=八cw

returnthis.fi(te《deM=>

);

//bettercodeclassSuperArrayextendsArray{

力•成co3P{

constkask=newSet(coi^pari$oiaArray);

return=>/MasM.has(elem));

}

)

6、避免类型检查

JavaScript是无类型的,意味着你可以传任意类型参数,这种自由度很容易让人

困扰,不自觉的就会去检查类型。仔细想想是你真的需要检查类型还是你的API

设计有问题?

//badcodefix八ctio八t^avclToTexas(vehicle){

if(vehicle/认sta八ccofBicycle){

vckicle.peda((this.currentL.ocatio^JnewLocatio^texa^));

}elseif(vehicle泗土即ceoFCar){

vehicle.dnve^kis.curre^tLocatioi^jnewLocatio八('texas'));

)

)

//bettercodcfuMtioi^travelToTexas(vehicle){

vehicle.moveCtki^curreiatLocation,MWLocatio^texas'));

}

如果你需要做静态类型检查,比如字符串、整数等,推荐使用Typescript,不

然你的代码会变得又臭又长。

//badcodefuMtio^co^biM(val^,㈤2){

if(typeofvail-===^ui^ber"&&typeofvatz===Sumter7||

typeofvail===KtH八g'&&typeofvat2==='string'){

returnval^L+valz;

}

tMrowMWError('MustbeoftypeStringorAJumfaer^);

)

//bettercodefuMtioi^coi^biM(valX,㈤2){

returnvalx+valZ;

]

复杂条件判断

我们编写js代码时经常遇到复杂逻辑判断的情况,通常大家可以用if/else或者

switch来实现多个条件判断,但这样会有个问题,随着逻辑复杂度的增加,代码

中的if/else/switch会变得越来越臃肿,越来越看不懂,那么如何更优雅的写判

断逻辑

I、if/else

点击列表按钮事件

*按钮点击事件

*status活动状态:1开团进行中2开团失败3商品售罄4开团成功S

系统取消

。八Butt。八Click=(s汝仅s)=》{

if($tatus--1){

sendLogCpKocessing)

j〃出pT。,灰dexPage')

if(status==2){

se^dLogCfaiT)

j(Akv\pTo(,FailPage,)

if(status==3){

sendLogCfaiP)

jumpToCFailPage1)

if($tatu$==4){

sc八dLogCs〃ccess)

ju^pTo(,SuccessPage,)

if(status==S){

sei^dLogCcancel1)

jukvipTo(,CaiacelPaget)

}c/“{

sc八WLogC。协ek)

jukv\pTo(,lndex,')

1

1

从上面我们可以看到的是通过不同的状态来做不同的事情,代码看起来非常不好

看,大家可以很轻易的提出这段代码的改写方案,switch出场:

2、switch/case

/**

*按钮点击事件

*@/%曰&{number}status活动状态:X开团进行中2开团失败3商品售罄4开团成功5

系统取消

*/const。八ButtonClick=(status)=>{

switch,(status}{

case1:

sei^dLogCprocessing1)

ju叫订o(,li^dexPage,)

break

case2:

case3:

se^dL-ogCfail')

jumpToCFailPage1)

break

case4:

se八dLogCsucccss')

jumpTo(SaccessPage')

break

ca$e5:

sei^dL-ogCcancel')

jui^pToCCaMelPage1)

break

default:

se八dLogCotheQ

jumpToC伍&x')

break

}

]

这样看起来比if/else清晰多了,细心的同学也发现了小技巧,case2和case3

逻辑一样的时候,可以省去执行语句和break,则case2的情况自动执行case3

的逻辑。

3、存放到Object

将判断条件作为对象的属性名,将处理逻辑作为对象的属性值,在按钮点击的时

候,通过对象属性查找的方式来进行逻辑判断,这种写法特别适合一元条件判断

的情况。

c。八允action={

,”:他dcxPageJ

2:

,3:[fai”FailPagel

4:Es(x"ess「S“"essPageZ

'51:[caMel1j'CaMelPage'Jj

default1:['otkcrV伍dex'J,

}/**

*按钮点击事件

*{iaukv\feer}status活动状态:工开团进行中2开团失败3商品售罄4升团成功5系

统取消

*/co^st。nButtcmClick=(st^tus)=>{

letaction=action$[status]||actio^s['default'],

logNaMC=actiov^O']J

pageNae=action[^L]

se八4Log(logNaM。)

j“MpTo(pageNaM6)

)

4、存放到Map

constaction=MWMap([

「process/认g'/伍dexPage'JJ,

t,,,

[2」[failJFailPage]]J

,,,,

[3,[failJFailPage]]J

[4j[Success1jSuccessPage1]]j

叵[,caMel,/CancelPage1]],

I1default1j['otherV伉dex[J

J)/**

*按钮点击事件

*@/%匕3{jAumfeer}status活动状态:工开团进行中2开团失败3商品售罄4开团成功5

系统取消

*/cc>HStcmButt。八Click=(status)=>{

letaction=actio八s.get(status)||actio^s.getCdefault1)

se八dLog(acti。八[O])

jumpTo(action[l])

}

这样写用到了es6里的M叩对象,是不是更爽了?Map对象和Object对象有

什么区别呢?

1.一个对象通常都有自己的原型,所以一个对象总有一个"prototype”键。

2.一个对象的键只能是字符串或者Symbols,但一个Map的键可以是任意

值。

3.你可以通过size属性很容易地得到一个M叩的键值对个数,而对象的键

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论