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 相关文章推荐
利用javascript中的call实现继承
Jan 22 Javascript
JavaScript 关键字屏蔽实现函数
Aug 02 Javascript
Javascript继承(上)——对象构建介绍
Nov 08 Javascript
javascript游戏开发之《三国志曹操传》零部件开发(二)人物行走的实现
Jan 23 Javascript
原生Js实现元素渐隐/渐现(原理为修改元素的css透明度)
Jun 24 Javascript
jquery插件开发之实现jquery手风琴功能分享
Mar 10 Javascript
javascript中slice(),splice(),split(),substring(),substr()使用方法
Mar 13 Javascript
JavaScript事件类型中焦点、鼠标和滚轮事件详解
Jan 25 Javascript
jQuery插件支持同一页面被多次调用
Feb 14 Javascript
AngularJS 路由详解和简单实例
Jul 28 Javascript
React-Router如何进行页面权限管理的方法
Dec 06 Javascript
AngularJS中ng-options实现下拉列表的数据绑定方法
Aug 13 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
根德YB400的电路分析
2021/03/02 无线电
php数字转汉字代码(算法)
2011/10/08 PHP
php 获取页面中指定内容的实现类
2014/01/23 PHP
MyEclipse常用配置图文教程
2014/09/11 PHP
php+MySQL实现登录时验证登录名和密码是否正确
2016/05/10 PHP
php 使用html5实现多文件上传实例
2016/10/24 PHP
php原生数据库分页的代码实例
2019/02/18 PHP
验证用户是否修改过页面的数据的实现方法
2008/09/26 Javascript
jquery 表格的增行删行实现思路
2013/03/21 Javascript
jquery删除提示框弹出是否删除对话框
2014/01/07 Javascript
JavaScript实现从数组中选出和等于固定值的n个数
2014/09/03 Javascript
Javascript原型链和原型的一个误区
2014/10/22 Javascript
jquery+php实现搜索框自动提示
2014/11/28 Javascript
js实现简单排列组合的方法
2016/01/27 Javascript
jQuery的ready方法实现原理分析
2016/10/26 Javascript
COM组件中调用JavaScript函数详解及实例
2017/02/23 Javascript
JS库之Highlight.js的用法详解
2017/09/13 Javascript
Angular4 Select选择改变事件的方法
2018/10/09 Javascript
layer更改皮肤的实现方法
2019/09/11 Javascript
微信小程序单选框自定义赋值
2020/05/26 Javascript
python设置windows桌面壁纸的实现代码
2013/01/28 Python
12步入门Python中的decorator装饰器使用方法
2016/06/20 Python
Python编程pygal绘图实例之XY线
2017/12/09 Python
Python将多份excel表格整理成一份表格
2018/01/03 Python
python如何在循环引用中管理内存
2018/03/20 Python
儿童学习python的一些小技巧
2018/05/27 Python
基于OpenCV python3实现证件照换背景的方法
2019/03/22 Python
Python 利用高德地图api实现经纬度与地址的批量转换
2019/08/14 Python
如何使用Django Admin管理后台导入CSV
2020/11/06 Python
详解python日志输出使用配置文件格式
2021/02/10 Python
香港百佳网上超级市场:PARKNSHOP.com
2020/06/10 全球购物
初级软件工程师面试题 Junior Software Engineer Interview
2015/02/15 面试题
2014年教研活动总结范文
2014/04/26 职场文书
考试没考好检讨书(精选篇)
2014/11/16 职场文书
红楼梦读书笔记
2015/06/25 职场文书
2016年度继续教育学习心得体会
2016/01/19 职场文书