【问题标题】:How to get return value from switch statement?如何从switch语句中获取返回值?
【发布时间】:2022-05-05 16:05:06
【问题描述】:

在 chrome 的控制台中,当我输入:

> switch(3){default:"OK"}
  "OK"

所以看起来 switch 语句有一个返回值。但是当我这样做时:

> var a = switch(3){default:"OK"}

抛出语法错误“Unexpected Token switch”

是否可以捕获switch的return语句?

【问题讨论】:

    标签: javascript


    【解决方案1】:

    这是因为当您将其放入 Chrome 控制台时,您会将其短路。它只是打印'OK',因为它达到了默认情况,而不是实际上返回一些东西。

    如果您想要返回某些内容,请将其粘贴在函数中,并在默认情况下返回“OK”。

    function switchResult(a){
        switch(a){
            default: 
                return "OK";
        }
    }
    
    var a = switchResult(3);
    

    【讨论】:

      【解决方案2】:

      也许有趣的是,如果将 ;break; 语句包装在一个函数中,则不需要杂乱无章的语句。 (如heloandre所述)

      function switchResult(a){   
          switch(a){   
              case 1: return "FOO";
              case 2: return "BAR";
              case 3: return "FOOBAR";
              default: return "OK";      
          }
      }
      var a = switchResult(3);
      

      【讨论】:

      • 不,switch 不需要break; 语句的原因是因为每个case 执行一个return,所以它不会落入下一个case。函数中的包装与它无关。
      【解决方案3】:

      ES6 允许您使用立即调用的 lambda 来做到这一点:

      const a = (() => {
        switch(3) {
          default: return "OK";
        }
      })();
      

      【讨论】:

      • 这里真的不需要使用 lambda,ES5 支持立即调用的函数就好了:console.log((function() { switch(3) { default: return "OK"; } })());
      • @hemp 这怎么比这个解决方案更好?在我看来是一样的
      • @darkace Lambda 语法需要 ES6,删除它使其与 ES5 兼容。并消除对后续读者的任何暗示,即 lambda 本身是有意义的。
      【解决方案4】:

      不,switch 没有返回值。您在控制台中看到的是 switch 内仅包含字符串文字值的语句的返回值。

      语句可以有返回值。例如赋值以赋值为返回值,后递增值返回递增后的结果:

      > a = 42;
      42
      > a++;
      43
      

      只包含一个值的语句会将该值作为返回值:

      > 42;
      42
      > "OK";
      "OK"
      

      这样的语句只在控制台中有用,例如用于显示变量的值。在代码中它不会完成任何事情。

      【讨论】:

        【解决方案5】:

        我最近不得不测试 switch 语句是否可以返回值。我很确定他们可以并实现了一个快速简洁的函数来在 FF 和 Chrome 控制台中对其进行测试。

        function switchController(setFlag) {
          switch (setFlag) {
            case true:   return setFlag;
            case false:  return setFlag;
          }
        }
        
        console.log(switchController(true));
        console.log(switchController(false));
        

        您应该在以下控制台中获得输出:

        true
        false
        

        您可以使用console.log()查看返回值

        【讨论】:

          【解决方案6】:

          Chrome 只是向您显示最后评估的值。 switch 没有输出。只需使用一个变量。

          var a; 
          
          switch(3)
          {
            default:
              a = "OK";
          }
          

          【讨论】:

            【解决方案7】:

            您在 chrome 开发工具中看到的是 switch 语句的 completion value。基本上是最后一个评估表达式的值(但不完全是,例如 var a = 42 的完成值不是 42)。完成值是 ECAMScript 中的一个结构,通常对程序员隐藏。不过,它也以return value of eval() 的形式出现。

            变量赋值的语法需要一个表达式在它的右手边,所以使用 switch 语句是一个语法错误:

            "var" <name> "=" <expression> 
            

            语句和表达式之间的区别基本上是表达式计算一个值,而语句不计算。例如,函数调用、算术和文字都是表达式。 “If”和“switch”语句不是。

            没有办法捕获任何语句的完成值,可能会将其包装在 eval 调用中:

            var a = eval('switch (3) { default: "OK" }')
            console.log(a) // => "OK"
            

            但是为此使用 eval 会not be a good idea

            不幸的是,没有很好的方法来归档您想做的事情。与提到的其他答案一样,您可以将开关包装在一个函数(或IIFE)中并使用return 语句来获取值:

            const a = (() => {
              switch(3) { default: return "OK"; }
            })();
            

            您可能会发现这不是一个理想的解决方案,而且您不是唯一一个遇到 JavaScript 问题的人。

            据我了解,这是pattern-matching ECAMScript 提案的动机之一。但该提案处于第 1 阶段,尚未准备好投入生产使用。

            此外,您可能希望以完全不需要switch 语句的方式编写代码。不久前,我遇到了以下在 Lua 中显然很常见但我从未在 JavaScript 中使用过的模式:

            您可以将所有案例作为属性放在 JavaScript 对象中,并使用函数作为值而不是单个 case 块中的逻辑,而不是使用 switch 语句。这可能看起来像这样:

            const cases = {
              "FOO": () => 1,
              "BAR": () => 2,
              "BAR": () => 3,
            };
            
            
            const value = "FOO";
            const result = cases[value]();
            console.log(result); // => 1
            

            而不是这个:

            let result;
            switch (value) {
                case "FOO":
                    result = 1;
                    break;
                case "BAR":
                    result = 2;
                    break;
                case "BAR":
                    result = 3;
                    break;
            }
            

            如果您需要非字符串案例,您可能需要使用Map

            【讨论】:

            • 只有在没有 default 大小写的情况下才能使用 Object 文字或 Map。你可能仍然会像cases[value]() || defaultValue 那样进行黑客攻击,但这很弱,因为如果你的 Object 或 Map 返回错误值(如 0 或 null),它将错误地落入defaultValue。所以...
            • 计算机程序的结构和解释如果不是 2022 年愚人节的玩笑,在 Javascript 中肯定会很有趣。
            【解决方案8】:

            你可以使用一个对象

            const a = { [enum.3]: "OK" }[3] ?? "default"
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2021-09-06
              • 2018-10-09
              • 2015-04-17
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多