在使用switch语句时,使用return语句是否比使用break语句更好?

283

选项1 - 使用 returnswitch

function myFunction(opt) {
  switch (opt) {
    case 1: return "One";
    case 2: return "Two";
    case 3: return "Three";

    default: return "";
  }    
}

选项二 - 使用 breakswitch

function myFunction(opt) {
  let retVal = "";

  switch (opt) {
    case 1: 
      retVal = "One";
      break;
    case 2: 
      retVal = "Two";
      break;
    case 3: 
      retVal = "Three";
      break;
  }

  return retVal;
}

我知道两种方法都可以,但哪一种更符合最佳实践呢?我倾向于使用Option 1 - 使用returnswitch,因为它更加简洁明了。


这里是我的具体示例的jsFiddle,使用了@ic3b3rg评论中提到的技巧:

let SFAIC = {};

SFAIC.common = {
  masterPages: {
    cs: "CS_",
    cp: "CP_"
  },
  contentPages: {
    cs: "CSContent_",
    cp: "CPContent_"    
  }
};

function getElementPrefix(page) {
  return (page in SFAIC.common.masterPages)
    ? SFAIC.common.masterPages[page]
    : (page in SFAIC.common.contentPages)
      ? SFAIC.common.contentPages[page]
      : undefined;
}

要调用该函数,我会按照以下方式操作:

getElementPrefix(SFAIC.common.masterPages.cs);
getElementPrefix(SFAIC.common.masterPages.cp);
getElementPrefix(SFAIC.common.contentPages.cs);
getElementPrefix(SFAIC.common.contentPages.cp);

问题在于它总是返回未定义(undefined)。我猜测这是因为它传递的是对象字面量的实际值而不是属性(property)。按照@ic3b3rg评论中描述的技术,我该怎么做来解决这个问题?

3个回答

358

使用 break 语句可以让您在函数中继续处理。如果您只想在函数中执行此操作,则从 switch 中返回即可。


8
所以,根据我问题中的示例,答案是肯定的。但是,如果你有一个需要继续执行的函数,显然你需要使用“break”。 - Code Maverick
12
马克·科斯特洛的回答让我更加思考你的问题。我认为你在寻找一般的“最佳实践”指南,但在你给出的具体例子中,最佳实践是return {1:"One",2:"Two,3:"Three"}[opt];。如果你需要默认值,那么它应该是var o={1:"One",2:"Two,3:"Three"}; return opt in o?o[opt]:""; - ic3b3rg
@ic3b3rg - 我已经编辑了我的问题,并尝试使用你的技巧return (opt in o) ? o[opt] : "";,但在我的具体情况下它总是返回默认值。 - Code Maverick
如果您想要进入到2级深度,那么您需要在函数中添加2个参数,并且逻辑代码如下:function getElementPrefix(type,page){return (type in SFAIC.common) && (page in SFAIC.common[type]) ? SFAIC.common[type][page] : undefined;} - ic3b3rg
那么如果我在每种情况下都返回,就不需要打破每种情况,对吗? - anhtv13
显示剩余6条评论

40

都不需要,因为对于一个非常简单的任务来说,两者都相当冗长。 你只需要这样做:

const result = ({
  1: 'One',
  2: 'Two',
  3: 'Three'
})[opt] ?? 'Default'  // opt can be 1, 2, 3 or anything (default)

当然,这也适用于字符串、混合使用或没有默认情况:

const result = ({
  first: 'One',
  'sec-ond': 'Two',
  3: 'Three'
})[opt]  // opt can be 'first', 'sec-ond' or 3

解释:

它通过创建一个对象,其中选项/情况是键,结果是值来工作。通过将选项放入括号中,您可以通过括号表示法访问与表达式匹配的键的值。

如果括号内的表达式不是有效的键,则返回undefined。我们可以使用nullish coalescing operator ??检测此未定义情况并返回默认值。

例子:

console.log('Using a valid case:', ({
  1: 'One',
  2: 'Two',
  3: 'Three'
})[1] ?? 'Default')

console.log('Using an invalid case/defaulting:', ({
  1: 'One',
  2: 'Two',
  3: 'Three'
})[7] ?? 'Default')
.as-console-wrapper {max-height: 100% !important;top: 0;}


1
这个方法叫什么? - Sourav Singh
2
@SouravSingh 我不认为它有一个名字。说实话,当我对这里的解决方案不满意时,我就想出了它。我猜我会把它叫做“对象切换”。 - leonheess
1
很好地利用了 Nullish 运算符! - BeHFaR
2
如果您有任何逻辑或计算,该方法将导致每次评估每个选项。然而,通过将每个选项变成一个函数而不是值(例如() => 'three'),您可以避免此问题:({...options})[1]()。或者,对于默认行为,({...options})[1]?.() ?? 'Default'。如果某些选项可能返回null且您不想覆盖它:(({...options})[1] ?? (() => 'Default'))() - Daniel
我想知道为什么这段很棒的代码没有名字。 - Mayeenul Islam

10

这要看情况,如果您的函数只包含switch语句,那么我认为可以。但是,如果您想在该函数中执行其他操作,则可能不是一个好主意。您还需要考虑现在和未来的要求。如果您想从选项一更改为选项二,那么就需要进行更多重构。

然而,考虑到if/else语句,最佳实践是采用以下做法:

var foo = "bar";

if(foo == "bar") {
    return 0;
}
else {
    return 100;
}

基于这点,可以认为选项一是更好的实践。

简而言之,没有明确的答案,只要你的代码符合一致、可读、可维护的标准——也就是说不要在应用程序中混用选项一和选项二,那么这是你应该遵循的最佳实践。


3
在这个例子中最佳实践是 return foo == "bar"; - ic3b3rg
11
如果我打扰到您了,我很抱歉,但在这种情况下,我可以将代码简化为以下两种形式之一:return foo == "bar" ? 0 : 100; 或者 return [100,0][foo == "bar"];。无论哪种形式都不会改变原本的意思,并且我会尽力使其更加通俗易懂。 - ic3b3rg
5
这句话的意思是:“这不应该是:return [100,0][+(foo == "bar")];吗?”你可以把它翻译成:“Shouldn't that be: return [100,0][+(foo == "bar")];?” - Queue
3
你是正确的,布尔值应该被转换为整数,但我会这样做:return [100,0][foo == "bar" & 1]; - ic3b3rg
1
@ic3b3rg - 这很漂亮;但是与使用一元加号相比,它的速度如何? - Queue
9
@ic3b3rg && Queue - 你想用这种技巧来维护别人的代码吗?(相信预编译器可以加速优化这样的东西) - T4NK3R

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接