运算符优先级与Javascript三元运算符

时间:2009-11-24 09:27:01

标签: javascript variable-assignment conditional-operator operator-precedence compound-assignment

我似乎无法将这个代码的第一部分(+ =)与三元运算符结合在一起。

h.className += h.className ? ' error' : 'error'

我认为此代码的工作方式如下:

h.className = h.className + h.className ? ' error' : 'error'

但这不正确,因为这会在我的控制台中出错。

所以我的问题是我应该如何正确地插入这段代码?

7 个答案:

答案 0 :(得分:141)

h.className = h.className + (h.className ? ' error' : 'error')

您希望运营商为h.className工作,最好具体一点 当然,h.className += ' error'不应该有任何伤害,但这是另一回事。

另请注意,+优先于三元运算符:JavaScript Operator Precedence

答案 1 :(得分:129)

这样想:

<variable> = <expression> ? <true clause> : <false clause>

语句执行的方式基本如下:

  1. <expression>评估为true,还是评估为false?
  2. 如果<expression>的计算结果为true,则<true clause>的值将分配给<variable><false clause>将被忽略,并执行下一条语句。
  3. 如果<expression>的评估结果为false,则会忽略<true clause>,并将<false clause>的值分配给<variable>
  4. 在这个和其他语言中用三元运算符实现的重要一点是,<expression>中的任何代码都应该在计算时产生一个布尔结果:true或false。

    如果你的例子在我的解释中用“添加到”替换“已分配给”,或者用你所使用的任何速记算术代替,或者类似。

答案 2 :(得分:10)

+=执行您想要的操作,但在其右侧的三元语句中,它会检查h.className是否为false,如果未定义则为{0}}。如果它是真实的(即如果已经指定了类名),则会添加一个带有空格的错误(即添加 new 类),否则会添加空格。

可以按照您的建议重写代码,但是您需要指定h.className用于真实性比较,而不是在三元运算符中使用其实际值,因此请确保您不要在进行三元操作的同时,要特别注意值的连接:

h.className = h.className + (h.className ? ' error' : 'error');

答案 3 :(得分:4)

=运算符的右侧从左到右进行评估。所以,

g.className = h.className + h.className ? ' error' : 'error';`

相当于

h.className = (h.className + h.className) ? ' error' : 'error';

等同于

h.className += h.className ? ' error' : 'error';

你必须在括号中分隔三元语句

h.className = h.className + (h.className ? ' error' : 'error');

答案 4 :(得分:3)

if (h.className) {
    h.className = h.className + ' error';
} else {
    h.className = h.className + 'error';
}

应该相当于:

h.className += h.className ? ' error' : 'error';

答案 5 :(得分:1)

我想选择Wayne的解释:

<variable> = <expression> ? <true clause> : <false clause>

让我们考虑两种情况:

case 1:
h.className += h.className ? 'true' : 'false'     
  • 赋值运算符正常工作,值附加
  • 第一次运行时,o / p:false
  • 第二次。 o / p:falsetrue - 值不断追加
  

情况2:   h.className = h.className + h.className? 'true':'false'

  • 结果与案例1不同
  • 第一次运行时,o / p:false
  • 第二次。 o / p:false - 值不会继续追加

explanation

  

在上面的代码中,案例1工作正常

,而  case2:

h.className = h.className + h.className ? 'true' : 'false'
is executed as 
 h.className = (h.className + h.className) ? 'true' : 'false'

h.className + h.className =&gt;被视为三元运算符的表达式作为三元运算符被赋予更高的优先级。所以,总是三元表达式的结果只是分配

您需要使用括号

来定义优先级

您需要在案例2的括号的帮助下定义评估顺序,以作为案例1工作

h.className = h.className + (h.className ? ' error' : 'error') 

答案 6 :(得分:1)

我知道这是一个非常古老的问题,但我对任何答案都不是100%满意,因为它们似乎都不完整。所以我们再次从第一批校长那里开始:

用户的总体目标:

汇总代码:“我希望在字符串中添加error类名称,如果字符串中已有类名,则可选择使用前导空格。”

最简单的解决方案

正如Kobi所指出的那样,5年前,在类名中占据领先地位不会对任何已知的浏览器造成任何问题,因此最短的正确解决方案实际上是:

h.className += ' error';

那应该是实际问题的实际答案


尽管如此,提出的问题是......

1)为什么这样做?

h.className += h.className ? ' error' : 'error'

条件/三元运算符的工作方式类似于if语句,它将truefalse路径的结果分配给变量。

因此代码有效,因为它的评估简单如下:

if (h.className IS NOT null AND IS NOT undefined AND IS NOT '') 
    h.className += ' error'
else
    h.className += 'error'

2)为什么这会破裂?

h.className = h.className + h.className ? ' error' : 'error'

问题陈述“在我的控制台中出现[n]错误”,这可能会误导您认为代码无法正常运行。实际上下面的代码确实在没有错误的情况下运行,但是如果字符串不是为空则它只​​返回'error'而如果字符串是<则返回'error' / em>为空,因此不符合要求

该代码始终会生成一个仅包含' error''error'的字符串,因为它会计算此伪代码:

if ((h.className + h.className) IS NOT null AND IS NOT undefined AND IS NOT '')
    h.className = ' error'
else
    h.className = 'error'

这样做的原因是加法运算符(+对普通民众)具有比条件/三元运算符(15)更高的“优先级”(6)。 我知道数字会向后显示

优先顺序只是意味着语言中的每种类型的运算符都以特定的预定义顺序进行评估(而不仅仅是从左到右)。

参考:Javascript Operator Precedence

如何更改评估顺序:

现在我们知道它失败的原因,你需要知道如何使它发挥作用。

其他一些答案谈论更改优先级,但你不能。优先权与语言紧密相连。这只是一组固定的规则...但是,您可以更改评估顺序 ......

我们的工具箱中可以更改评估顺序的工具是分组操作符(也就是括号)。它通过确保在括号外的操作之前评估括号中的表达式来实现此目的。这就是他们所做的一切,但这就足够了。

Brackets的工作原因仅仅是因为它们(分组运算符)的优先级高于所有其他运算符(“现在有0级”)。

只需添加括号,更改评估顺序,以确保在简单字符串连接之前首先执行条件测试:

h.className = h.className + (h.className ? ' error' : 'error')

我现在将这个答案留给其他人看不见的生锈:)