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


116

我似乎无法与三元运算符结合使用此代码的第一部分(+ =)。

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

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

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

但这是不正确的,因为这会导致控制台出现错误。

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

Answers:


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

您希望操作员为之工作h.className,最好对此有所具体。
当然,不应有任何伤害 h.className += ' error',但这是另一回事。

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


3
我认为应该指出的是,虽然不会造成任何损害h.className += ' error',但如果字符串最初为空,它也会在字符串的开头留一个空格。我相信三元运算的目的是生成一个看上去干净的字符串。
JMTyler 2011年

@JMTyler-这正是我的意思-如果为了从一开始就保留一个空间而完成了所有操作,那我就不值得了。(边缘情况包括确切的jQuery或XPath选择器)。不管怎样,谢谢。
科比

@Kobi +1仅用于运算符优先级警告!
Ed Chapel

129

这样想:

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

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

  1. <expression>计算为true,或者它评估为假的?
  2. 如果<expression>计算结果为true,则将的值<true clause>分配给<variable><false clause>将忽略,并执行下一条语句。
  3. 如果<expression>评估为false,则将<true clause>其忽略,并将的值<false clause>分配给<variable>

使用此语言和其他语言的三元运算符要实现的重要一点是,无论代码中的内容是什么,<expression>在评估时都应产生布尔结果:true或false。

在您的示例中,我在解释中将“分配给”替换为“添加到”,或者对于您正在使用的速记算法(如果有的话)进行替换。


请注意,如果完美的注释合适,请注意:)它跳过了为何左手表达式首先“组合在一起”的任何解释(即,因为+优先级高于条件/三元运算符(实际上,条件运算符几乎总是最后一个) –在任何
Gone Coding

10

可以执行所需的+=操作,但是在其右侧的三元语句中,它将检查是否h.className为假,如果未定义则为假。如果是事实(即,如果已经指定了一个类名),则错误添加一个空格(即添加一个新的类),否则添加一个不带空格的错误。

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

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

13
是的,undefined这不是的,只是像对待一样
David Hedlund

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');


1

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

用户的总体目标:

总结代码:“我希望在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'

问题指出“在我的控制台中出现错误”,这可能使您误以为代码不起作用。实际上,以下代码可以运行,没有错误,但是如果字符串不为空,则仅返回“错误”,如果字符串且不符合要求,则仅返回“ error” 。

该代码始终会导致只包含' 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运算符优先级

如何更改评估顺序:

现在我们知道了失败的原因,您需要知道如何使其工作。

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

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

方括号之所以起作用,是因为它们(分组运算符)的优先级高于所有其他运算符(“现在有一个0级”)。

通过简单地添加方括号,您可以更改求值顺序,以确保在简单字符串连接之前先执行条件测试:

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

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


1

我想选择韦恩的解释:

<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?'真假'

  • 结果与情况1不同
  • 第一次运行时,o / p:false
  • 第二次。o / p:否-值不会不断追加

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=>被视为三元运算符的表达式,因为三元运算符具有更高的优先级。因此,总是只分配三元表达式的结果

您需要使用方括号定义优先级

您需要使用方括号定义要考虑的评估顺序,以使情况2与情况1相同

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

1
这里的术语不太正确。优先级是语言固有的,您无需定义。相反,您通过引入方括号(比所有其他运算符都有更高的优先级)来定义求值顺序
Gone Coding 2014年

@TrueBlueAussie我接受。感谢您的阅读+1
Angelin Nadar 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.