JS代码简洁方式之函数方法详解


Posted in Javascript onJuly 28, 2020

函数的参数越少越好

有一个准则是:如果你的函数参数超过两个,就应该改为对象传入。

这样做是合理的,因为当函数参数超过两个时,参数顺序开始变得难以记忆,而且容易出现一种很尴尬的情况:比如我只需要传入第三个参数,因为其自身顺序的原因,不得不补齐前两个根本用不上的参数,以让它顺利排在第三位。

// bad
const createArticle = (title, author, date, content) => { }
createArticle('震惊,一男子竟偷偷干这事', 'zhangnan', '2020/06/29', '某天深夜,我喝多了点酒...')

// good
const createArticle = ({title, author, date, content}) => { }
createArticle({
 title: '震惊,一男子竟偷偷干这事',
 author: 'zhangnan',
 date: '2020/06/29',
 content: '某天深夜,我喝多了点酒...'
})

保持函数的单一职责原则

这是软件开发领域亘古不变的一个真理,让一个函数只专注于一件事情,能够很好的解耦各个功能之间的联系,使得后续对某一个功能进行更改时,不用担心会影响其他模块。

假设我们现在有一个需求:现在需要给班里的每一个同学发放假短信通知,如果是男生,就用电信主机号来发,如果是女生,则用联通主机号发,同时额外发送一封爱心邮件。实现如下:

// bad 代码挤成一堆,很难理清
// 男生女生的通知方式还有所不同,后期如果要改动女生的通知方式,很难保证不会影响到男生
// 因为大家都写在同一个函数里

const notifyStudents = (studentList) => {
 studentList.forEach(student => {
  if (student.gender === 'male') {
   const sender1 = new SmsSender({ carrier: '电信' });
   sender1.init();
   sender1.sendTo(student) 
  } else {
   const sender2 = new SmsSender({ carrier: '联通' });
   sender2.init();
   sender2.sendTo(student);
   
   const sender3 = new EmailSender({ type: 'QQ邮箱' });
   sender3.connect();
   sender3.sendTo(student)
  }
 })
}


// good 函数拆分,各司其职,清晰明了
// 虽然看起来代码量多了一点点
// 但是分工明确,互不影响
const initSmsSender = (carrier) => {
 const sender = new SmsSender({ carrier });
 sender.init();
}

const initEmailSender = (type) => {
 const sender = new EmailSender({ type });
 sender.connect();
}

const notifyMales = (studentList) => {
 const smsSender = initSmsSender('电信');
 const maleList = studentList.filter(student => student.gender === 'male');
 
 maleList.forEach(male => smsSender.sendTo(male));
}

const notifyFemales = (studentList) => {
 const smsSender = initSmsSender('联通');
 const emailSender = initEmailSender('QQ邮箱');
 
 const femaleList = studentList.filter(student => student.gender === 'female');
 
 femaleList.forEach(female => {
  smsSender.sendTo(female);
  emailSender.sendTo(female);
 })
}

封装条件语句

像有一些条件语句,可能存在很多与或非逻辑,如果直接写在函数里面,每次都需要重新理一遍,费时费力。把一堆条件语句封装在一个函数里面,不仅遵循单一职责原则,也将使得阅读更加方便。

// bad
const shouldIBuyThisPhone = (phone) => {
 const {price, year, brand} = phone;
 if (price > 5000 && year === new Date.getFullYear() && brand === 'huawei') {
  // 马上剁手
 }
}

// good
const isHuaweiFlagShipThisYear = ({ price, year, brand }) => {
 const HIGH_PRICE = 5000;
 return price > HIGH_PRICE && year === new Date.getFullYear() && brand === 'huawei'
}

const shouldIBuyThisPhone = (phone) => {
 if (isHuaweiFlagShipThisYear(phone)) {
  // 马上剁手
 }
}

高层函数不要依赖具体实现

在一些动作函数中,常见的一种情况是传一个flag参数,通过对标志变量的判断,做出不同的响应动作。

这样其实是不太好的,因为这会使这个动作函数内部去维护一些判断逻辑,如果flag参数比较多,函数内部的区分情况也会很多。

另外这里也涉及一种思想:具体的差异实现应该由使用者提供,而不是统一执行者去维护。

或者称之为依赖倒置原则:高层模块(打印)不应该依赖于实现细节(某个人的喜好)。

比如,我现在有一台打印机?️,小A喜欢用单面黑白横向打印,小B喜欢用单面彩色竖向打印,小C喜欢用双面彩色横向打印等等等等。作为一台打印机,它需要去维护一个人员喜好列表吗?如果有一千个人使用它,那它就需要维护一千条数据。

它只是一台打印机!告诉它配置,然后打印,就完事了!打印机只专注于打印这件事本身。

// bad 需要判断标志变量,同时做出不同的相应动作
const print = (person) => {
 if (person === 'A') {
  device.print({ 
   page: 1, 
   color: 'gray', 
   orientation: 'landscape' 
   
  })
 }
 
 else if (person === 'B') {
  device.print({ 
   page: 1, 
   color: 'colorful', 
   orientation: 'vertical' 
  })
 }
 
 else if (person === 'C') {
  device.print({ 
   page: 2, 
   color: 'colorful' ,
   orientation: 'landscape'
  })
 }
 
 ......
 
}


// good
const print = (config) => {
 device.print(config)
}

写在最后

总结:

  • 函数传参越少越好,多了改为对象传入
  • 保持函数单一职责原则
  • 封装条件语句
  • 高层函数不要依赖具体实现

到此这篇关于JS代码简洁方式之函数方法详解的文章就介绍到这了,更多相关JS代码简洁方式 函数内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
jQuery中将函数赋值给变量的调用方法
Mar 23 Javascript
Js四则运算函数代码
Jul 21 Javascript
jQuery 计算iframe 窗口大小的方法
May 13 Javascript
web前端开发JQuery常用实例代码片段(50个)
Aug 28 Javascript
一波JavaScript日期判断脚本分享
Mar 06 Javascript
bootstrap和jQuery.Gantt的css冲突 如何解决
May 29 Javascript
Bootstrap标签页(Tab)插件使用方法
Mar 21 Javascript
JS中IP地址与整数相互转换的实现代码
Apr 10 Javascript
微信小程序实现的贪吃蛇游戏【附源码下载】
Jan 03 Javascript
js数组常用最重要的方法
Feb 04 Javascript
jquery+ajax实现上传图片并显示上传进度功能【附php后台接收】
Jun 06 jQuery
JavaScript数组排序功能简单实现
May 14 Javascript
vue 组件之间事件触发($emit)与event Bus($on)的用法说明
Jul 28 #Javascript
JavaScript前端开发时数值运算的小技巧
Jul 28 #Javascript
js实现全选和全不选
Jul 28 #Javascript
浅谈vue中$bus的使用和涉及到的问题
Jul 28 #Javascript
js实现全选和全不选功能
Jul 28 #Javascript
JavaScript React如何修改默认端口号方法详解
Jul 28 #Javascript
vue内置组件component--通过is属性动态渲染组件操作
Jul 28 #Javascript
You might like
apache+php完美解决301重定向的两种方法
2011/06/08 PHP
使用PHP Socket 编程模拟Http post和get请求
2014/11/25 PHP
php 二维数组快速排序算法的实现代码
2017/10/17 PHP
基于jQuery捕获超链接事件进行局部刷新代码
2012/05/10 Javascript
一个简单的JS鼠标悬停特效具体方法
2013/06/17 Javascript
js操作iframe父子窗体示例
2014/05/22 Javascript
javascript日期格式化方法汇总
2015/10/04 Javascript
JavaScript动态生成二维码图片
2016/04/20 Javascript
js禁止Backspace键使浏览器后退的实现方法
2017/09/01 Javascript
node+express+ejs使用模版引擎做的一个示例demo
2017/09/18 Javascript
vue轮播图插件vue-concise-slider的使用
2018/03/13 Javascript
如何把vuejs打包出来的文件整合到springboot里
2018/07/26 Javascript
微信小程序中使用echarts的实现方法
2019/04/24 Javascript
TypeScript 引用资源文件后提示找不到的异常处理技巧
2020/07/15 Javascript
vue中使用腾讯云Im的示例
2020/10/23 Javascript
通过实例解析js可枚举属性与不可枚举属性
2020/12/02 Javascript
[01:18]DOTA2超级联赛专访hanci ForLove淘汰感言曝光
2013/06/04 DOTA
[55:48]VGJ.S vs TNC Supermajor 败者组 BO3 第二场 6.6
2018/06/07 DOTA
[01:51]历届DOTA2国际邀请赛举办地回顾 TI9落地上海
2018/08/26 DOTA
python的dict,set,list,tuple应用详解
2014/07/24 Python
python操作ssh实现服务器日志下载的方法
2015/06/03 Python
以视频爬取实例讲解Python爬虫神器Beautiful Soup用法
2016/01/20 Python
python+opencv打开摄像头,保存视频、拍照功能的实现方法
2019/01/08 Python
pandas 数据结构之Series的使用方法
2019/06/21 Python
用sqlalchemy构建Django连接池的实例
2019/08/29 Python
python爬虫 Pyppeteer使用方法解析
2019/09/28 Python
对python中 math模块下 atan 和 atan2的区别详解
2020/01/17 Python
Python使用Pygame绘制时钟
2020/11/29 Python
美国知名奢侈美容品牌零售商:Cos Bar
2017/04/21 全球购物
广告设计专业自荐信范文
2013/11/14 职场文书
汽车专业求职信
2014/06/05 职场文书
学习作风建设心得体会
2014/10/22 职场文书
2016年读书月活动总结范文
2016/04/06 职场文书
react国际化react-intl的使用
2021/05/06 Javascript
动漫APP软件排行榜前十名,半次元上榜,第一款由腾讯公司推出
2022/03/18 杂记
nginx共享内存的机制详解
2022/03/21 Servers