使用对象字面量替代JavaScript的switch语句

JavaScript的switch语句是我发现很难记住语法的几个事情之一(很高兴VS Code有自动补全)。从语法上讲,它也有些不太协调,因为它是唯一不使用花括号的语句,并且你需要记住在每个case后面加上break。此外,它的性能也不太好,因为它的控制流是过程式的。

幸运的是,JavaScript的对象字面量对于我能想到的大多数switch语句用例来说是一个相当不错的替代方案。思路是为每个switch语句中的case定义一个键,然后可以使用传递给switch语句的表达式直接访问其值。

let fruit = 'oranges';

switch (fruit) {
  case 'apples':
    console.log('Apples');
    break;
  case 'oranges':
    console.log('Oranges');
    break;
}
// 输出:'Oranges'

const logFruit = {
  'apples': () => console.log('Apples'),
  'oranges': () => console.log('Oranges')
};

logFruit[fruit](); // 输出:'Oranges'

虽然这种方式更易读且更简洁,但它也更快。然而,我们还没有解决一个问题:default情况。为了处理它,我们只需添加一个'default'键,并检查表达式的值是否存在于我们的对象中。

let fruit = 'strawberries';

switch (fruit) {
  case 'apples':
    console.log('Apples');
    break;
  case 'oranges':
    console.log('Oranges');
    break;
  default:
    console.log('Unknown fruit');
}
// 输出:'Unknown fruit'

```js
const logFruit = {
  'apples': () => console.log('苹果'),
  'oranges': () => console.log('橙子'),
  'default': () => console.log('未知水果')
};

(logFruit[fruit] || logFruit['default'])(); // 输出:'未知水果'

最后,我们的对象字面量替代方案应该能够处理类似于没有break语句时的情况。这只是简单地提取和重用对象字面量中的逻辑。

let fruit = 'oranges';

switch (fruit) {
  case 'apples':
  case 'oranges':
    console.log('已知水果');
    break;
  default:
    console.log('未知水果');
}
// 输出:'已知水果'

const knownFruit = () => console.log('已知水果');
const unknownFruit = () => console.log('未知水果');

const logFruit = {
  'apples': knownFruit,
  'oranges': knownFruit,
  'default': unknownFruit
};

(logFruit[fruit] || logFruit['default'])(); // 输出:'已知水果'

最后,我们可以将这个逻辑通用化并提取到一个简单的可重用函数中。我们将为它提供查找对象和一个可选的默认情况名称(我们将默认为_default以避免任何冲突)。这个函数将返回一个具有适当查找逻辑的函数,我们可以使用它来替换任何switch语句。

const switchFn = (lookupObject, defaultCase = '_default') =>
  expression => (lookupObject[expression] || lookupObject[defaultCase])();
const knownFruit = () => console.log('已知水果');
const unknownFruit = () => console.log('未知水果');

const logFruit = {
  'apples': knownFruit,
  'oranges': knownFruit,
  'default': unknownFruit
};

const fruitSwitch = switchFn(logFruit, 'default');

fruitSwitch('apples'); // 输出:'已知水果'
fruitSwitch('pineapples'); // 输出:'未知水果'