JavaScript作用域变量用于switch case语句?

31

在C语言中,您可以通过switch case限定变量的作用域,就像这样

使用以下代码时,在javascript中我会收到意外的标记:

const i = 1

switch (i) {
    // variables scoped to switch
    var s
    var x = 2342
    case 0:
      s = 1 + x
      break
    case 1:
      s = 'b'
      break
}

有没有其他方法可以做到这一点,或者我应该只是在switch之外声明我的变量?
编辑:
这是我考虑过的一个解决方法,但最终没有起作用。原因是每个case都有自己的作用域。

const i = 1

switch (i) {
    case i:
      // variables scoped to switch
      var s
      var x = 2342
    case 0:
      s = 1 + x
      break
    case 1:
      s = 'b'
      break
}


1
你的 JS 中的 switch 语句无效。你可以在 case 内或 switch 外定义变量。 - Ionut Necula
1
既然显然你想在 switch 之后访问 s,为什么要将其限定在 switch 语句内部呢?! - deceze
@deceze 这只是一个例子,有很多原因会让人想要这样做。 - Philip Kirkbride
@PhilipKirkbride 请查看我的更新答案,提供了一个解决方法,可以得到您想要的结果。 - Scott Marcus
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Philip Kirkbride
在 switch 中使用 { code } 就像ABC一样简单。 - Phani Rithvij
5个回答

96

一些替代方案:

/* curly braces inside the case */

const i = 1

switch (i) {
  case 0: {
    let x = 2342;
    let s = 1 + x;
    console.log(x+' & '+s+' from inside');
  } break;
  case 1: {
    let x = 2342;
    let s = 'b';
    console.log(x+' & '+s+' from inside'); /* 2342 & b from inside */
  } break;
}

console.log(x+' & '+s+' from outside'); /* Uncaught ReferenceError */
或者
/* curly braces outside the switch */

const i = 1

{
  let x = 2342;
  let s;
  switch (i) {
    case 0:
      s = 1 + x;
      break;
    case 1:
      s = 'b';
      break;
  }
  console.log(x+' & '+s+' from inside'); /* 2342 & b from inside */
}

console.log(x+' & '+s+' from outside'); /* Uncaught ReferenceError */

4
TC39委员会犯了一个显而易见的错误。 - pdoherty926
1
@pdoherty926 哎呀,就像什么鬼一样 :D - Robo Robok

13

由于 var 实际上只会在 函数 作用域中创建变量,使用它是非常无意义的。如果要在函数作用域以下的粒度上工作,则必须使用 let 和支持它的浏览器/编译器,然后引入一个新的块,在其中可以对事物进行范围限制(在 switch 中,它只是无效语法):

if (true) {
    let s;

    switch (i) {
        ...
    }
}

这将s的作用域限制在if块内,就本质而言,这与此处的"switch作用域"是相同的。

如果您无法支持let,则需要使用IIFE:

(function () {
    var s;

    switch (...) ...
})();

3
第一个例子根本不需要 if。只需用 {} 包装代码即可。 - Scott Marcus
我不确定在什么情况下可能会被解释为对象文字,因此我建议使用安全的 if 语句。当然,你可以尝试不使用它。 - deceze
4
我已经尝试过了。这是完全合法的。就像你的 if 分支不会被误认为是对象字面量一样,将整个块包围起来也不会产生混淆。 - Scott Marcus
MDN 中提到,case 中的 {} 是有效的。 - kiranvj

3
不,这是无效的语法。在 switch 语句中应该有一个 case 或 default 语句。你可以在这里查看规范:http://www.ecma-international.org/ecma-262/5.1/#sec-12.11 你也可以尝试在 JSLinter 中输入代码并查看错误信息: http://jslint.com/
Expected 'case' and instead saw 'var'.

您考虑的解决方法与将它们放在switch语句外是一样的。请记住,var具有函数级别的作用域,而不是块级别的作用域。这意味着它们绑定到包含switch的整个函数。您应该在switch之外声明它们,因为那里是可以访问它们的地方。
const i = 1;
var s;
var x = 2342;

switch (i) {
  case 0:
    s = 1 + x;
    break;
  case 1:
    s = 'b';
    break;
  default:
    break;
}

console.log("s is " + s);

0

JavaScript 定义了三个作用域级别:

  • 全局 - 任何未在函数中声明的内容
  • 函数 - 使用 var 关键字在函数中声明的内容
  • 块级 - 使用 let 在块容器 ({}) 中声明的内容

因此,要创建一个完整的构造作用域,您有两个选择:函数或块级

为了获得您想要的函数行为:

const i = 1

function doSwitch(data){

  // variables are not scoped to switch, but are 
  // scoped to the function, which only contains 
  // the switch.
  var s;
  var x = 2342;
  
  switch (data) {
    case 0:
      s = 1 + x;
      break;
    case 1:
      s = 'b';
      break;
    default:
      s = "other";
  }

  console.log("s is " + s)

}

doSwitch(18);

或者,为了使用let块获得功能。

const i = 1;

// Wrapping the switch in its own block allows for let to work:
{
      // variables are not scoped to switch, but are 
      // scoped to the function, which only contains 
      // the switch.
      let s;
      let x = 2342;
      
      switch (i) {
        case 0:
          s = 1 + x;
          break;
        case 1:
          s = 'b';
          break;
        default:
          s = "other";
      }

      console.log("s is " + s)
}

// Test:
console.log(s, x);  // ReferenceError


1
你不能在 switch 的中间声明它,这就是问题所在。 - StudioTime
1
@DarrenSweeney 没错,谢谢指出。一开始没注意到。答案已经修改。 - Scott Marcus

0
应该在 switch 外声明。以下可能会有所帮助:
var i = 1, x = 2342;
var s;
switch (i)
 {        
    case 0:
      s = 1 + x;
      break;
    case 1:
      s = 'b';
      break;
}
console.log("s is " + s);

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