简体   繁体   English

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

[英]Operator precedence with Javascript Ternary operator

I cant seem to wrap my head around the first part of this code ( += ) in combination with the ternary operator. 我似乎无法将这个代码的第一部分(+ =)与三元运算符结合起来。

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

The way i think this code works is as following: 我认为这段代码的工作方式如下:

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

But that isn't correct because that gives a error in my console. 但这不正确,因为这会在我的控制台中出错。

So my question is how should i interpet this code correctly? 所以我的问题是我应该如何正确地插入这段代码?

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

You want the operator to work for h.className , better be specific about it. 您希望运算符为h.className工作,更好地了解它。
Of course, no harm should come from h.className += ' error' , but that's another matter. 当然, h.className += ' error'不应该有任何伤害,但这是另一回事。

Also, note that + has precedence over the ternary operator: JavaScript Operator Precedence 另请注意, +优先于三元运算符: JavaScript运算符优先级

Think of it this way: 想一想:

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

The way the statement gets executed is basically as follows: 语句执行的方式基本如下:

  1. Does <expression> evaluate to true, or does it evaluate to false? <expression>评估为true,还是评估为false?
  2. If <expression> evaluates to true, then the value of <true clause> is assigned to <variable> , <false clause> is ignored, and the next statement is executed. 如果<expression>计算结果为true,则将<true clause>值赋给<variable> ,忽略<false clause> ,并执行下一个语句。
  3. If <expression> evaluates to false, then <true clause> is ignored and the value of <false clause> is assigned to <variable> . 如果<expression>计算结果为false,则忽略<true clause> ,并将<false clause>值赋给<variable>

The important thing to realise with the ternary operator in this and other languages is that whatever code is in <expression> should produce a boolean result when evaluated: either true or false. 在这个和其他语言中使用三元运算符实现的重要一点是, <expression>中的任何代码都应该在计算时产生一个布尔结果:true或false。

In the case of your example replace "assigned to" in my explanation with "added to", or similar for whichever shorthand arithmetic you are using, if any. 在你的例子的情况下,在我的解释中用“添加到”替换“已分配给”,或者对于你使用的任何简写算法都是类似的,如果有的话。

The += does what you want, but in the ternary statement at the right hand of it, it checks if h.className is falsey, which it would be if it was undefined. +=做你想要的,但是在它右边的三元语句中,它会检查h.className是否为falsey,如果它是未定义的话。 If it's truthy (ie if a class name is already specified), then error is added with a space (ie adding a new class), otherwise it's added without the space. 如果它是真实的(即,如果已经指定了类名),则添加带有空格的错误(即添加类),否则添加没有空格的错误。

The code could be rewritten as you suggest, but you need to specify that h.className is to be used for truthiness-comparison, rather than for using its actual value, in the ternary operator, so make sure you don't bother with the concatenation of values at the same time as doing your ternary operation: 代码可以按照你的建议重写,但你需要指定h.className用于真实性比较,而不是在三元运算符中使用它的实际值,所以请确保你不要打扰在进行三元操作的同时连接值:

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

The right hand side of the = operator is evaluated left to right. =运算符的右侧从左到右进行评估。 So, 所以,

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

is equivalent to 相当于

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

To be equivalent to 相当于

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

you have to separate the ternary statement in parenthesis 你必须在括号中分开三元语句

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

should be equivalent of: 应相当于:

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

I know this is a very old question, but I am not 100% happy with any of the answers as they all seem incomplete. 我知道这是一个非常古老的问题,但我对任何答案都不是百分之百满意,因为它们似乎都不完整。 So here we go again from first principals: 所以这里我们再次从第一个校长:

The user's overall aim: 用户的总体目标:

Summarising the code: "I wish to add an error class name to a string, optionally with a leading space if there are already class names in the string." 总结代码: “我希望在字符串中添加一个error类名,如果字符串中已有类名,则可选择使用前导空格。”

Simplest solution 最简单的解决方案

As Kobi pointed out, 5 years ago, having a leading space in class names will not cause any problems with any known browsers, so the shortest correct solution would actually be: 正如Kobi在5年前指出的那样,在类名中拥有领先的空间不会对任何已知的浏览器造成任何问题,因此最短的正确解决方案实际上是:

h.className += ' error';

That should have been the actual answer to the actual problem . 这应该是实际问题实际答案


Be that as it may, the questions asked were... 尽管如此,提出的问题是......

1) Why did this work? 1)为什么这样做?

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

The conditional/ternary operator works like an if statement, that assigns the result of its true or false paths to a variable. 条件/三元运算符的工作方式类似于if语句,它将其truefalse路径的结果分配给变量。

So that code worked because it is evaluated simply as: 所以代码工作,因为它被简单地评估为:

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

2) and why did this break? 2)为什么这会破裂?

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

The question states "that gives a[n] error in my console", which may mislead you into thinking the code does not function . 问题陈述“在我的控制台中出现[n]错误”,这可能会误导您认为代码不起作用 In fact the following code does run, without error , but it simply returns ' error' if the string was not empty and 'error' if the string was empty and so did not meet the requirements . 其实下面的代码并运行,没有错误 ,但它只是返回“错误”如果字符串不是空的,“错误”如果字符串空的,所以并不能满足要求

That code always results in a string that contains only ' error' or 'error' because it evaluates to this pseudo code: 该代码总是产生一个只包含' error''error'的字符串,因为它计算为这个伪代码:

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

The reason for this is that the addition operator ( + to the common folk) has higher "precedence" (6) than the conditional/ternary operator (15). 其原因是加法运算符( +对普通民众)具有比条件/三元运算符(15)更高的“优先级”(6)。 I know the numbers appear backwards 我知道这些数字是倒退的

Precedence simply means that each type of operator in a language is evaluated in a particular predefined order (and not just left-to-right). 优先级仅意味着语言中的每种类型的运算符都以特定的预定义顺序(而不仅仅是从左到右)进行评估。

Reference: Javascript Operator Precedence 参考: Javascript运算符优先级

How to change the order of evaluation: 如何更改评估顺序:

Now we know why it fails, you need to know how to make it work. 现在我们知道它失败的原因,你需要知道它是如何工作的。

Some other answers talk about changing the precedence , but you can't . 其他一些答案谈论改变优先权 ,但你不能 Precedence is hard-wired into the language. 优先权与语言紧密相连。 That is just a fixed set of rules... However, you can change the order of evaluation ... 这只是一套固定的规则......但是,您可以更改评估顺序 ......

The tool in our toolbox that can change the order of evaluation is the grouping operator (aka brackets). 我们的工具箱中可以更改评估顺序的工具是分组操作符(也就是括号)。 It does this by ensuring the expressions in the brackets are evaluated before operations outside the brackets. 它通过确保在括号外的操作之前评估括号中的表达式来实现此目的。 That's all they do, but that's enough. 这就是他们所做的一切,但这就足够了。

Brackets work simply because they (grouping operators) have higher precedence than all other operators ("there is now a level 0"). 括号的工作原理很简单,因为它们(分组运算符)的优先级高于所有其他运算符 (“现在有0级”)。

By simply adding brackets you change the order of evaluation to ensure the conditional test is performed first, before the simple string concatenation: 通过简单地添加括号,您可以更改评估顺序,以确保在简单字符串连接之前首先执行条件测试:

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

I will now leave this answer to rust unseen among the others :) 我现在将这个答案留给其他人看不见的生锈:)

I would like to pick explanation of wayne : 我想选择Wayne的解释:

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

Lets consider both the cases: 让我们考虑两种情况:

case 1:
h.className += h.className ? 'true' : 'false'     
  • assignment operator works fine and value gets appended 赋值运算符工作正常,值被追加
  • when runs for the first time, o/p: false 当第一次运行时,o / p:false
  • 2nd time. 第二次。 o/p: falsetrue -- values keeps appending o / p:falsetrue - 值不断追加

case2: h.className = h.className + h.className ? case2:h.className = h.className + h.className? 'true' : 'false' '真假'

  • the result is not same as case 1 结果与案例1不同
  • when runs for the first time, o/p: false 当第一次运行时,o / p:false
  • 2nd time. 第二次。 o/p: false -- values doesn't keep appending o / p:false - 值不会继续追加

explanation

In the above code, case 1 works fine 在上面的代码中,案例1工作正常

whereas case2: 而案例2:

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

h.className + h.className => considered as expression for ternary operator as ternary operator is given higher precedence. h.className + h.className =>被认为是三元运算符的表达式,因为三元运算符具有更高的优先级。 so, always the result of the ternary expression is just assigned 所以,总是只分配三元表达式的结果

You need to define the precedence by using brackets 您需要使用括号来定义优先级

You need to define the order of evaluation to be considered with the help of brackets for case 2 to work as case 1 您需要在案例2的括号的帮助下定义要考虑的评估顺序,以作为案例1

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM