【发布时间】: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
在 chrome 的控制台中,当我输入:
> switch(3){default:"OK"}
"OK"
所以看起来 switch 语句有一个返回值。但是当我这样做时:
> var a = switch(3){default:"OK"}
抛出语法错误“Unexpected Token switch”
是否可以捕获switch的return语句?
【问题讨论】:
标签: javascript
这是因为当您将其放入 Chrome 控制台时,您会将其短路。它只是打印'OK',因为它达到了默认情况,而不是实际上返回一些东西。
如果您想要返回某些内容,请将其粘贴在函数中,并在默认情况下返回“OK”。
function switchResult(a){
switch(a){
default:
return "OK";
}
}
var a = switchResult(3);
【讨论】:
也许有趣的是,如果将 ;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。函数中的包装与它无关。
ES6 允许您使用立即调用的 lambda 来做到这一点:
const a = (() => {
switch(3) {
default: return "OK";
}
})();
【讨论】:
不,switch 没有返回值。您在控制台中看到的是 switch 内仅包含字符串文字值的语句的返回值。
语句可以有返回值。例如赋值以赋值为返回值,后递增值返回递增后的结果:
> a = 42;
42
> a++;
43
只包含一个值的语句会将该值作为返回值:
> 42;
42
> "OK";
"OK"
这样的语句只在控制台中有用,例如用于显示变量的值。在代码中它不会完成任何事情。
【讨论】:
我最近不得不测试 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()查看返回值
【讨论】:
Chrome 只是向您显示最后评估的值。 switch 没有输出。只需使用一个变量。
var a;
switch(3)
{
default:
a = "OK";
}
【讨论】:
您在 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。所以...
你可以使用一个对象
const a = { [enum.3]: "OK" }[3] ?? "default"
【讨论】: