理论 Coffeescript Switch 语句难题

Theoretical Coffeescript Switch Statement Conundrum

前言

这可能没有真正的实现,但在阅读 another post on coffeescript's 2 switch usages 之后,我决定尝试一下,发现了这个相当奇怪的问题。

咖啡脚本

type = 'guidance'

s = switch
  when type is 'guidance'
   'g'
  when type is 'vulnerability'
   'v'
  else
   'foo'

console.log s #g

转译javascript

var s, type;

type = 'guidance';

s = (function() {
  switch (false) {
    case type !== 'guidance':
     return 'g';
  case type !== 'vulnerability':
     return 'v';
  default:
     return 'foo';
 }
})();

console.log(s); //g

难题

我没有得到的是 case 表达式被编译为相反的值。 Coffeescript when type is 'guidance' 应该 转译为以下 javascript case type === 'guidance' 对吗?

如果您使用 s = switch true,则 case 表达式会正确呈现 case type === 'guidance'。无论渲染的 javaScript 个 case 表达式如何,结果都是相同的。

无论出于何种原因,Coffeescript 转译器都会生成一个 switch 语句来匹配显式值 false,而不是 true。因此,case 表达式与 when 子句的意思相反。当 when 子句中的表达式为 true 时,生成的 switch 语句将选择 case 因为它正在寻找 相反的 条件为 false.

我不认为这是一个问题,因为它按预期工作:-)

其中的原因,我只能猜测(可能是编译器有一些注释)。他们很可能需要将所有这些表达式转换为布尔值——他们希望它像 if 语句一样工作,但是 switch 确实使用 === 运算符与给定的价值。所以你不能做

switch (true) {
    case 1: …
    case []: …
    case "true": …
}

因为其中 none 会起作用,而它们都是真值。所以你可以使用 double not operator:

switch (true) {
    case !!( 1 ): …
    case !!( [] ): …
    case !!( "true" ): …
}

并且任何这些表达式都将匹配 true。但是,您可以通过将外部 ! 移动到比较的另一侧(!true)来稍微减少代码大小,并获得等效的

switch (false) {
    case !( 1 ): …
    case !( [] ): …
    case !( "true" ): …
}

您可以在 coffeescript docs 中看到这个确切的模式。现在,显然编译器足够聪明,可以将 ===== 表达式上的 ! 组合成 !=!==,但这不适用于任意表达式。

如果你问我,他们应该把它编译成一系列 if elses。