JS代码简洁之道--函数

函数的参数越少越好

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

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

// 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)
}

写在最后

总结:

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

另外,帮大佬发个字节跳动今日头条校园招聘宣传,北广深均有,Inspire creativity, enrich life。欢迎各位小鲜肉报名加入 今日头条校招传送门

原文链接:juejin.im

上一篇:is-safe-integer
下一篇:手写一个简易的Hooks风格多模块Redux

相关推荐

  • 🙋Hanjst汉吉斯特改进+enSafeExpression安全表达式等

    Hanjst汉吉斯特模版语言及模版引擎,近期持续改进升级。 这次改进主要是增加了对安全输出表达式兼容,由于涉及到对软件开发过程中的效率和软件运行效率的平衡和取舍,所以多写了几句,以描述这个权衡利弊对...

    2 个月前
  • 🙋Hanjst汉吉斯特升级:+showImageAsync及性能改进等

    自2019年元旦🙋Hanjst汉吉斯特 模板语言及其编译引擎发布,已经过去一年多了。 这期间随着 🙋Hanjst汉吉斯特 的推广应用,我们也陆续发布了如下一些更新内容: 🛠️Hanjst/汉吉...

    3 个月前
  • 🙋Hanjst汉吉斯特优化+JsonDataFromScript等

    近日继续对 🙋Hanjst汉吉斯特优化改进。这次的改进思考是从服务器端返回的 HanjstJsonData的容器设计问题。目前的做法是服务器端的HanjstJsonData放入终端页面的一个Div元...

    1 个月前
  • 😉我用 Nuxt.js 仿了个掘金

    前言 首先肯定是要夸夸掘金啦,最开始从 CSDN 到 博客园 再到 掘金,个人感觉掘金的技术氛围非常的nice,真是个宝藏社区👏。技术文章大多以前端为主,对前端开发者非常友好,质量也是歪瑞古的。

    2 个月前
  • 😀一个原生js弹幕库

    danmujs 😀一个原生js弹幕库,基于 CSS3 Animation 地址、核心代码 本项目基于 rcbullets,项目约70%的代码基于rcbullets,首先要感谢这个项目的作者,如...

    5 个月前
  • 🕵️‍♀️由原型到JS中的“模拟类”

    讲述了有关 JavaScript 中原型相关知识,又引出了 JavaScript 中的“类“究竟是什么?,以及一系列相关问题。 一、前置知识 1、JavaScript 的面向对象(OOP) ​ 面向...

    3 个月前
  • 🔥《吊打面试官》系列 Node.js 必知必会必问!

    (/public/upload/f204a3b224d986128f1b4d9b8d06cd17) 前言 codeing 应当是一生的事业,而不仅仅是 30 岁的青春🍚 本文已收录 Git...

    4 个月前
  • 💖CSS + JS 送学妹满屏幕小爱心

    故事开始 午饭时间,暗恋已久的学妹拉着我的衣袖:“学长学长,你能不能让这些爱心变成五颜六色的吗~”。 我在旁边笑开了花~~~ image.png(/public/upload/04aaa24e...

    3 个月前
  • (干货👍)从详细操作js数组到浅析v8中array.js

    前言 最近在写面试编程题,经常用到数组,经常想偷个懒,用它提供的方法,奈何还是对数组方法使用不熟练,导致写了很多的垃圾代码,很多地方稍加修改的话肯定变得简洁高效优雅👊 所以✍这篇文章本着了解一下Ja...

    9 天前
  • (vuejs学习)2、使用ElementUI(*)

    1.element安装 开发环境是win10,一到node官网下载node的.msi包(https://npm.taobao.org/mirrors/node/v10.16.0/nodev10.16....

    1 年前

官方社区

扫码加入 JavaScript 社区