117

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

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

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

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

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

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

4

7 回答 7

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

您希望操作员为 工作h.className,最好具体说明。
当然,不应该受到伤害 h.className += ' error',但那是另一回事。

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

于 2009-11-24T09:30:29.770 回答
129

这样想:

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

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

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

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

在您的示例中,将我的解释中的“分配给”替换为“添加到”,或者对于您使用的任何速记算术(如果有)类似。

于 2009-11-24T09:35:37.847 回答
10

The+=做你想做的事,但是在它右边的三元语句中,它检查是否h.className为假,如果它是未定义的。如果它是真实的(即如果已经指定了类名),则在错误中添加一个空格(即添加一个类),否则将在没有空格的情况下添加它。

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

h.className = h.className + (h.className ? ' error' : 'error');
于 2009-11-24T09:34:44.273 回答
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');
于 2009-11-24T09:30:41.533 回答
3
if (h.className) {
    h.className = h.className + ' error';
} else {
    h.className = h.className + 'error';
}

应该相当于:

h.className += h.className ? ' error' : 'error';
于 2009-11-24T09:34:58.930 回答
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 ?'真假'

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

explanation

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

而案例2:

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') 
于 2011-07-12T07:34:15.263 回答
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'因为它计算为这个伪代码:

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

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

于 2014-06-11T15:29:00.937 回答