The case
and default
clauses are like labels: they indicate possible places that control flow may jump to. However, they don't create lexical scopes themselves (neither do they automatically break out — as demonstrated above). For example:
const action = "say_hello";
switch (action) {
case "say_hello":
const message = "hello";
console.log(message);
break;
case "say_hi":
const message = "hi";
console.log(message);
break;
default:
console.log("Empty action received.");
}
This example will output the error "Uncaught SyntaxError: Identifier 'message' has already been declared", because the first const message = 'hello';
conflicts with the second const message = 'hi';
declaration, even when they're within their own separate case clauses. Ultimately, this is due to both const
declarations being within the same block scope created by the switch
body.
To fix this, whenever you need to use let
or const
declarations in a case
clause, wrap it in a block.
const action = "say_hello";
switch (action) {
case "say_hello": {
const message = "hello";
console.log(message);
break;
}
case "say_hi": {
const message = "hi";
console.log(message);
break;
}
default: {
console.log("Empty action received.");
}
}
This code will now output hello
in the console as it should, without any errors.