JavaScript 中 switch 语句的四种进阶写法与技巧

作者:代码拾荒

时间:2026-10-25

浏览:598

本文深入解析 JavaScript 中 switch 语句的四种不同写法。从传统的变量匹配,到利用 === 严格相等匹配的常量 case,再到通过 IIFE(立即调用函数表达式)实现类似 C# 的 switch 表达式功能,最后介绍使用策略模式结合 find 方法的高级应用。文章通过具体代码示例,展示了如何在不同场景下优化分支逻辑,提升代码可读性与灵活性。

文章目录

引言

JavaScript 中的 switch 语句其实隐藏着多种写法,你了解几种?无论你是否知晓,作者起初也只知其一。

通常我们认为 JavaScript 的 switch 只有一种标准写法,但在处理分支逻辑时,实现方式却多种多样。除了常见的 if 分支和标准的 switch 分支外,还可以采用策略模式,若将条件运算符纳入考量,恰好可以归纳为四种主要形式。

switch一般写法

本文重点探讨 switch 语句。通常大家熟悉的写法是 switch 后接变量或表达式,case 后接常量。例如,针对百分制成绩进行评级:90分及以上为优秀,80至89分为良好,60至79分为合格,60分以下为不合格。使用 switch 实现这一逻辑的大致代码如下:

function calcGrade(score) {
    const line = score / 10 | 0;
    switch (line) {
        case 10: case 9:
            return "优秀";
        case 8:
            return "良好";
        case 7: case 6:
            return "合格";
        default:
            return "不合格";
    }
}

代码中的 score / 10 | 0 与 Math.floor(score / 10) 效果一致,均是通过除以 10 后取整数部分来实现分级。

这种 switch 用法中规中矩,通过取整技巧避免了冗长的 if...else 分支判断,算是一种巧妙的实现方式。

然而,如果规则发生变化,例如将合格与良好的分界线从 80 分下调至 75 分,该如何调整?

按上面取整的办法依然可以,不过这次除数不再是 10,而是 5。相应地,case 也多了很多:

  • 18、19、20 对应优秀
  • 15、16、17 对应良好
  • 12、13、14 对应合格
  • 其余情况为不合格

编写多达 9 个 case 显然繁琐,此时使用 if...else 可能更为合适。

switch简单写法

真的如此吗?其实 switch 还有更简洁的写法:

function calcGrade(score) {
    switch (true) {
        case score >= 90:
            return "优秀";
        case score >= 75:
            return "良好";
        case score >= 60:
            return "合格";
        default:
            return "不合格";
    }
}

这种写法看似反常,并非习惯中的 switch 变量匹配 case 常量,而是 switch 常量匹配 case 表达式。运行这段代码会发现其完全正常,原因在于 switch 和 case 实际上是按照 ===(严格相等)进行匹配的。switch 和 case 后均可接表达式,并不局限于常量。

没错,就是表达式。

因此,在上述示例中,将 switch(true) 替换为 switch( 2 > 1) 也能达到相同的效果。

思路已打开。switch 究竟有多少种写法已不再重要,接下来我们将探讨 switch 的变体应用。

IIFE 封装

看到 C# 拥有 switch 表达式功能,是否心生羡慕?JavaScript 中能否实现?

无需羡慕,在 JavaScript 中一切皆可为表达式;若不能,通过 IIFE(立即调用函数表达式)封装即可实现。

function calcGrade(score) {
    return (value => {
        switch (true) {
            case value >= 90:
                return "优秀";
            case value >= 75:
                return "良好";
            case value >= 60:
                return "合格";
            default:
                return "不合格";
        }
    })(score);
}

注意此处将 score 作为 IIFE 的参数传入,因为在实际使用中,传入的往往是一个表达式。这种情况下应提前求值且仅求值一次,以避免潜在的副作用。

封成策略

然而,仅如此封装意义不大。若需进一步封装,可将其转化为策略模式:

function calcGrade(score) {
    return ((value, rules) => rules.find(({ t }) => t(value)).v)(
        score,
        [
            { t: n => n >= 90, v: "优秀" },
            { t: n => n >= 75, v: "良好" },
            { t: n => n >= 60, v: "合格" },
            { t: () => true, v: "不合格" },
        ]
    );
}

每个策略对象包含一个测试器(t)和一个返回值(v)。测试器是一个判断函数,接收待判断的值,即 switch (表达式) 中的表达式。该表达式在作为 IIFE 参数传入前已提前求值。应用策略的过程简单直接:找到第一个符合条件的策略,并提取其对应的值。

当然,对于简单场景使用策略模式略显繁琐。在真正需要策略模式的场景中,策略通常包含一个行为(即函数),而不仅仅是一个值。

我们知道,在标准 switch 语句中,所有 case 处于同一作用域,因此不能在不同 case 中声明同名的局部变量。虽然使用 { }(块级作用域)包裹可以解决此问题,但代码可读性较差,且容易遗漏 break(break)。若采用策略模式,代码结构会更清晰,且无需担心 break 的问题:

此处为了演示,策略行为中先输出成绩,再返回等级。

function calcGrade(score) {
    return ((value, rules) => rules.find(({ t }) => t(value)).fn(value))(
        score,
        [
            {
                t: n => n >= 90,
                fn: score => {
                    const grade = "优秀";
                    console.log(grade, score);
                    return grade;
                }
            },
            {
                t: n => n >= 75,
                fn: score => {
                    const grade = "良好";
                    console.log(grade, score);
                    return grade;
                }
            },
            {
                t: n => n >= 60,
                fn: score => {
                    const grade = "合格";
                    console.log(grade, score);
                    return grade;
                }
            },
            {
                t: () => true,
                fn: score => {
                    const grade = "不合格";
                    console.log(grade, score);
                    return grade;
                }
            },
        ]
    );
}

代码长度有所增加,因为包含了策略行为的逻辑。若将 switch 视为表达式使用,策略部分应尽可能简洁。上述代码中策略行为相似,可封装为一个函数,从而写成表达式形式:

function calcGrade(score) {
    const printGrade = (grade, score) => {
        console.log(grade, score);
        return grade;
    };
    return ((value, rules) => rules.find(({ t }) => t(value)).fn(value))(
        score,
        [
            { t: n => n >= 90, fn: score => printGrade("优秀", score) },
            { t: n => n >= 75, fn: score => printGrade("良好", score) },
            { t: n => n >= 60, fn: score => printGrade("合格", score) },
            { t: () => true, fn: score => printGrade("不合格", score) },
        ]
    );
}

现在看起来是否更加规范?

上述代码形式各异,但核心功能相似,并无绝对的优劣之分。顺眼的写法即优雅,反之则不然。根据具体场景选择合适的方法即可。上述代码使用 find() 来查找策略,若改用 filter(),则呈现另一种景象。

以上就是 JavaScript 中 switch 四种写法的详细内容,更多关于 JS switch 写法的资料请持续关注本站相关文章!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章