JS函数优化:参数精简、单一职责与依赖倒置实战
本文详解JavaScript中函数设计的四个核心原则:通过对象传参减少参数数量,遵循单一职责使函数专注单一功能,封装复杂条件语句提升可读性,以及利用依赖倒置解耦高层逻辑与具体实现。结合代码示例,展示如何编写简洁、易维护的JS代码。
减少函数参数数量
在编写JavaScript函数时,应尽可能减少参数数量。
一个实用的准则是:如果函数参数超过两个,建议改为通过对象传入。
这种做法的合理性在于,当参数数量过多时,参数的顺序容易令人混淆,且常出现尴尬场景:例如仅需传入第三个参数,却因顺序限制不得不补全前两个无用的参数,以便其正确排在第三位。
// 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代码简洁方式 函数内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
ES6模块化中js文件怎么用import和export交互
2026-11-05 17:00:48
JS读取本地文件时报错或无响应的常见原因
2026-11-05 16:32:31
let、const与var的区别:JavaScript变量声明最佳实践
2026-11-05 14:16:38
JS中直接定义静态二维数组的字面量写法
2026-11-05 14:16:08
JS 怎么查找字符串中所有匹配项的位置
2026-11-05 14:15:53
