在Javascript中有条件地初始化常量

83

从ES6开始,我们有了const

这是不允许的:

const x; //declare first
//and then initialize it
if(condition) x = 5;
else x = 10;

这是有道理的,因为它防止我们在常量初始化之前使用它。

但是如果我这样做

if(condition)
    const x = 5;

else 
    const x = 10;

x 变为块级作用域。

那么如何有条件地创建常量?


2
这是我在Javascript中所缺少的东西,而Java做得非常好。 - WORMSS
3个回答

87

正如您所知,您的问题在于const必须在声明表达式中初始化。

这并不意味着您分配给常量的值必须是字面值。它实际上可以是任何有效的表达式 - 三目运算符:

const x = IsSomeValueTrue() ? 1 : 2;

或者只是将它分配给变量的值?

let y = 1;
if(IsSomeValueTrue()) {
    y = 2;
}

const x = y;
你当然可以将它分配给函数的返回值,例如:
function getConstantValue() {
    return 3;
}

const x = getConstantValue();

所以有很多方法可以使价值动态化,你只需要确保它只在一个地方分配即可。


1
如果我们有很长的条件和计算(就像我的情况一样),使用函数方式会更加清晰,而使用三元运算符则会显得混乱。 - Frozen Crayon
1
我同意函数方法可能是最干净的,特别是对于更复杂的条件。只需选择最适合您用例的方法 :) - Hecksa
我更喜欢最终的选项(函数),因为它允许您在不依赖于类的其余部分的情况下更改、重用甚至单元测试逻辑。 - ssube
虽然其他答案也是正确的,但我会接受这个,因为它展示了不同的方法。 - Frozen Crayon

34

如果三元运算符因其难以阅读而不可行,那么唯一的选择是IIFE,虽然它很麻烦但可以流畅地阅读:

const x = (() => {
  if (condition)
    return 5
  else
    return 10
})();

const 的语义是只能被赋值一次。这种情况下应该使用let

let x;
if(condition) x = 5;
else x = 10;

从我的个人经验来看,大约95%的变量都是const。如果一个变量必须是let,就让它保持不变;由于意外重新赋值引起的错误概率微乎其微。


1
IIFE 似乎是根据 OP 在评论中定义的用例最整洁的解决方案。 - CodingIntrigue
8
如果一个三元表达式不易读懂,那么立即调用函数表达式(IIFE)怎么可能“更好”呢?这显然更加难以阅读。 - ssube
5
IIFEs是已建立的语言结构,可以被流利的JS开发者自动解释,箭头函数使它们更简洁,适当的缩进和括号也有帮助。这是主观的,但应该注意到答案中没有“更好”的说法,并且“地球”这个词并不能使论点更有说服力。即使IIFEs对你无效,也并不意味着它们对每个人都无效,感谢您提供的评论和反对票。 - Estus Flask
2
IIFEs有其时机和地点,但这可以通过调用兄弟方法来解决。仅仅为了内联该方法而使用IIFE(JIT将自行执行)会留下比三元运算符更复杂的代码。 - ssube
@ssube,我喜欢IIFE解决方案,因为它表示一次性赋值。如果需要一个命名方法以供重用,我会考虑这是否应该是一个const。对于OP的用例来说,可读性比三元运算符更好,因为它们需要复杂的逻辑和重复。我认为这就是他们在第一句话中所表达的意思。 - CodingIntrigue

9
假设在这两个实例中都要声明const,你可以使用三元赋值运算符来实现:
const x = condition ? 5 : 10;

我猜他们被教导三元运算符 :? 是一种邪恶的、不可读的风格。它违背了“不要重复自己”的原则,所谓的“可读性”就是基于这个原则的 :) - Little Alien
如果我要声明多个常量,我必须为每个常量重复条件。x = cond ? a : b; y = cond ? e : f - Frozen Crayon
3
阅读 const [a,b] = [x,y] 的赋值语句。 - Little Alien
哦,解构。太棒了! - Frozen Crayon
@ArjunU。是的,有效的。否则你就不得不引入不必要的变量。 - CodingIntrigue

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