用于 JavaScript 中字符串匹配的 Switch 语句

2022-08-30 01:00:27

如何为以下条件编写开关?

如果 url 包含 “foo”,则为 “bar”。settings.base_url

以下内容正在实现所需的效果,但我有一种感觉,这在切换中更易于管理:

var doc_location = document.location.href;
var url_strip = new RegExp("http:\/\/.*\/");
var base_url = url_strip.exec(doc_location)
var base_url_string = base_url[0];

//BASE URL CASES

// LOCAL
if (base_url_string.indexOf('xxx.local') > -1) {
    settings = {
        "base_url" : "http://xxx.local/"
    };
}

// DEV
if (base_url_string.indexOf('xxx.dev.yyy.com') > -1) {
    settings = {
        "base_url" : "http://xxx.dev.yyy.com/xxx/"
    };
}

答案 1

你不能在开关中做到这一点,除非你正在做完整的字符串匹配;那就是做子字符串匹配。正如肖恩在评论中指出的那样,这并不完全正确。请参阅末尾的注释。

如果你很高兴你顶部的正则表达式剥离了你不想在比赛中比较的所有内容,你不需要子字符串匹配,可以做到:

switch (base_url_string) {
    case "xxx.local":
        // Blah
        break;
    case "xxx.dev.yyy.com":
        // Blah
        break;
}

...但同样,只有当这是您要匹配的完整字符串时,这才有效。如果是“yyy.xxx.local”,而您当前的代码与“xxx.local”分支中的代码匹配,它将失败。base_url_string


更新:好的,所以从技术上讲,你可以使用子字符串匹配,但在大多数情况下我不建议使用它。操作方法如下(实际示例):switch

function test(str) {
    switch (true) {
      case /xyz/.test(str):
        display("• Matched 'xyz' test");
        break;
      case /test/.test(str):
        display("• Matched 'test' test");
        break;
      case /ing/.test(str):
        display("• Matched 'ing' test");
        break;
      default:
        display("• Didn't match any test");
        break;
    }
}

这是有效的,因为JavaScript switch语句的工作方式,特别是两个关键方面:首先,情况是按源文本顺序考虑的,其次,选择器表达式(关键字后面的位)是在计算该情况时计算的表达式(而不是像其他一些语言中的常量)。因此,由于我们的测试表达式是 ,因此生成的第一个表达式将是被使用的表达式。casetruecasetrue


答案 2

RegExp 也可以与该方法一起用于输入字符串。match

为了确保我们在子句中有匹配项,我们将根据成功的 属性测试原始值(提供给语句)。casestrswitchinputmatch

input 是正则表达式的静态属性,包含原始输入字符串。

失败时,它将返回 。为了避免异常错误,我们在访问属性之前使用可选的链接运算符(或旧版 ES 中的逻辑条件运算符)。matchnull||input

const str = 'XYZ test';

switch (str) {
  case str.match(/^xyz/)?.input:
    console.log("Matched a string that starts with 'xyz'");
    break;
  case str.match(/test/)?.input:
    console.log("Matched the 'test' substring");        
    break;
  default:
    console.log("Didn't match");
    break;
}

另一种方法是使用构造函数将结果数组转换为字符串,该数组必须只有 1 个元素(没有捕获组),并且必须使用量词 () 捕获整个字符串。如果发生故障,对象将变为字符串。这似乎不太方便。String().*null'null'

const str = 'XYZ test';

switch (str.toLowerCase()) {
  case String(str.match(/^xyz.*/i)):
    console.log("Matched a string without case sensitivity");
    break;
  case String(str.match(/.*tes.*/)):
    console.log("Matched a string using a substring 'tes'");
    break;
}

无论如何,一个更优雅的解决方案是使用该方法而不是,即 与 它只返回一个布尔值,并且更容易匹配而不区分大小写。testmatch/^find-this-in/.test(str)switch (true)

const str = 'haystack';

switch (true) {
  case /^hay.*/i.test(str):
    console.log("Matched a string that starts with 'hay'");
    break;
}

但是,在这种情况下使用语句也是可读的ifelseelse if