发布于 2026-01-06 3 阅读
0

JavaScript/TypeScript 中 switch 语句的新编码风格

JavaScript/TypeScript 中 switch 语句的新编码风格

我最近采用了一种新的switchJavaScript(严格来说是 TypeScript)语句编码风格,我很想知道大家对此有何看法!

在讨论这种风格之前,让我先解释一下我试图解决的问题。switch 语句在不同 case 之间出现一些重复的代码并不罕见,但每个 case 又有所不同,以至于很难将其抽象化。我们来看这个用 ES5 编写的例子(我保证这样做是有原因的)。

switch (body.type) {
  case 'isBasic':
    var entry = getBasicEntry(body.id);
    console.log('Processing basic entry "' + entry.name + '"');
    doBasicProcessing(entry);
    break;

  case 'isCustom':
    var entry = getCustomEntry(body.id);
    console.log('Processing custom entry "' + entry.name + '"');
    doCustomprocessing(entry);
    break;

  default:
    throw new Error('Unknown flag ' + myFlag);
}
Enter fullscreen mode Exit fullscreen mode

很好,这是一个基本的 switch 语句,而且运行良好。现在,让我们把它转换成 ES2015+ 代码。

switch (body.type) {
  case 'isBasic':
    const entry = getBasicEntry(body.id);
    console.log(`Processing basic entry "${entry.name}"`);
    doBasicProcessing(entry);
    break;

  case 'isCustom':
    const entry = getCustomEntry(body.id);
    console.log(`Processing custom entry "${entry.name}"`);
    doCustomprocessing(entry);
    break;

  default:
    throw new Error(`Unknown flag ${myFlag}`);
}
Enter fullscreen mode Exit fullscreen mode

糟糕,SyntaxError运行这段代码时会抛出异常!问题在于同一个作用域内不能声明两次同一个const变量名entry。由于作用域规则的限制,整个switch语句只属于一个作用域。

我们可以通过给每个情况使用不同的变量名来解决这个问题entry,但说实话,我觉得这样做有点麻烦。我们也可以为每个情况创建一个辅助函数,但对于这么短的 case 语句来说,我觉得这样做有点多余。

这就是我最终的发现,我已经开始在我的所有代码中使用它了:

switch (body.type) {
  case 'isBasic': {
    const entry = getBasicEntry(body.id);
    console.log(`Processing basic entry "${entry.name}"`);
    doBasicProcessing(entry);
    break;
  }

  case 'isCustom': {
    const entry = getCustomEntry(body.id);
    console.log(`Processing custom entry "${entry.name}"`);
    doCustomprocessing(entry);
    break;
  }

  default: {
    throw new Error(`Unknown flag ${myFlag}`);
  }
}
Enter fullscreen mode Exit fullscreen mode

我把每个 case 语句都用 `<case>` 包裹起来{},这样每个 case 语句就创建一个新的作用域。这解决了问题,而且我觉得这种方法挺优雅的。不过这种做法并不常见。

大家觉得怎么样?这种方法可行吗?你们有没有其他不同的方法?欢迎在评论区分享!

更新:

感谢大家迄今为止的讨论,非常棒!我最终创建了一个名为conditional-reduce的新模块,它自动化了一种我之前没有想到的方法:

const { reduce } = require('conditional-reduce');

console.log(reduce('dog', {
  dog: () => 'Dogs are great pets',
  cat: () => 'Cat\'s are also great'
})); // Prints "Dogs are great pets"

console.log(reduce('bird', {
  dog: () => 'Dogs are great pets',
  cat: () => 'Cat\'s are also great'
})); // Throws 'Invalid conditional value "bird"' exception
Enter fullscreen mode Exit fullscreen mode
const { curry } = require('conditional-reduce');

const dogReducer = curry({
  dog: () => 'Dogs are great pets',
  cat: () => 'Cat\'s are also great'
});

console.log(dogReducer('dog')); // Prints "Dogs are great pets"
console.log(dogReducer('bird')); // Throws 'Invalid conditional value "bird"' exception
Enter fullscreen mode Exit fullscreen mode

感谢@avalander@john_papa 的讨论,才有了这篇文章!

文章来源:https://dev.to/nebrius/a-new-coding-style-for-switch-statements-in-javascript-typescript-ipe