JS代码简洁方式之函数方法详解
函数的参数越少越好
有一个准则是:如果你的函数参数超过两个,就应该改为对象传入。
这样做是合理的,因为当函数参数超过两个时,参数顺序开始变得难以记忆,而且容易出现一种很尴尬的情况:比如我只需要传入第三个参数,因为其自身顺序的原因,不得不补齐前两个根本用不上的参数,以让它顺利排在第三位。
//bad
constcreateArticle=(title,author,date,content)=>{}
createArticle('震惊,一男子竟偷偷干这事','zhangnan','2020/06/29','某天深夜,我喝多了点酒...')
//good
constcreateArticle=({title,author,date,content})=>{}
createArticle({
title:'震惊,一男子竟偷偷干这事',
author:'zhangnan',
date:'2020/06/29',
content:'某天深夜,我喝多了点酒...'
})
保持函数的单一职责原则
这是软件开发领域亘古不变的一个真理,让一个函数只专注于一件事情,能够很好的解耦各个功能之间的联系,使得后续对某一个功能进行更改时,不用担心会影响其他模块。
假设我们现在有一个需求:现在需要给班里的每一个同学发放假短信通知,如果是男生,就用电信主机号来发,如果是女生,则用联通主机号发,同时额外发送一封爱心邮件。实现如下:
//bad代码挤成一堆,很难理清
//男生女生的通知方式还有所不同,后期如果要改动女生的通知方式,很难保证不会影响到男生
//因为大家都写在同一个函数里
constnotifyStudents=(studentList)=>{
studentList.forEach(student=>{
if(student.gender==='male'){
constsender1=newSmsSender({carrier:'电信'});
sender1.init();
sender1.sendTo(student)
}else{
constsender2=newSmsSender({carrier:'联通'});
sender2.init();
sender2.sendTo(student);
constsender3=newEmailSender({type:'QQ邮箱'});
sender3.connect();
sender3.sendTo(student)
}
})
}
//good函数拆分,各司其职,清晰明了
//虽然看起来代码量多了一点点
//但是分工明确,互不影响
constinitSmsSender=(carrier)=>{
constsender=newSmsSender({carrier});
sender.init();
}
constinitEmailSender=(type)=>{
constsender=newEmailSender({type});
sender.connect();
}
constnotifyMales=(studentList)=>{
constsmsSender=initSmsSender('电信');
constmaleList=studentList.filter(student=>student.gender==='male');
maleList.forEach(male=>smsSender.sendTo(male));
}
constnotifyFemales=(studentList)=>{
constsmsSender=initSmsSender('联通');
constemailSender=initEmailSender('QQ邮箱');
constfemaleList=studentList.filter(student=>student.gender==='female');
femaleList.forEach(female=>{
smsSender.sendTo(female);
emailSender.sendTo(female);
})
}
封装条件语句
像有一些条件语句,可能存在很多与或非逻辑,如果直接写在函数里面,每次都需要重新理一遍,费时费力。把一堆条件语句封装在一个函数里面,不仅遵循单一职责原则,也将使得阅读更加方便。
//bad
constshouldIBuyThisPhone=(phone)=>{
const{price,year,brand}=phone;
if(price>5000&&year===newDate.getFullYear()&&brand==='huawei'){
//马上剁手
}
}
//good
constisHuaweiFlagShipThisYear=({price,year,brand})=>{
constHIGH_PRICE=5000;
returnprice>HIGH_PRICE&&year===newDate.getFullYear()&&brand==='huawei'
}
constshouldIBuyThisPhone=(phone)=>{
if(isHuaweiFlagShipThisYear(phone)){
//马上剁手
}
}
高层函数不要依赖具体实现
在一些动作函数中,常见的一种情况是传一个flag参数,通过对标志变量的判断,做出不同的响应动作。
这样其实是不太好的,因为这会使这个动作函数内部去维护一些判断逻辑,如果flag参数比较多,函数内部的区分情况也会很多。
另外这里也涉及一种思想:具体的差异实现应该由使用者提供,而不是统一执行者去维护。
或者称之为依赖倒置原则:高层模块(打印)不应该依赖于实现细节(某个人的喜好)。
比如,我现在有一台打印机