VK said:
I'm not sure how is it called in the books, I used to call it "If
Shortcut".
Other names are "conditional expression", "questionmark-colon
operator" or (misguidedly) "the ternary operator". (The third is only
identifying because ?: is the *only* ternary operator in the
language. A ternary operator is an operator that takes three
arguments, whereas * is a binary operator)).
So instead if writing: ....
you write:
x = (someConditionIsTrue) ? variant1 : variant2;
Exactly.
Another way to look at it is syntactically. In most programming
languages there are (at least) two syntactic categories: Expressions
and statements. An expression is evaluted to a value, and a statement
is executed to have an effect. Examples of expressions are, e.g., "42"
and "x+y". Examples of statements are, e.g.,"x=42;" and "while(true){}".
Since we want programs to be useful, we need a way to not always
execute exactly the same code. For that we use conditional brances.
The typical branch is the "if" statement:
if (conditionExpression) {
conditionalStatements1;
} else {
conditionalStatements1;
}
This is itself a statement. Depending on the value of the condition
expression, it has the same behavior as on of the conditioned
statements. It is not decided until runtime which one it is.
So, we have the syntactic category of statements, and we want to make
a choice at runtime about which choice of statement we want to
execute. The entire compund of this switching logic and both
statements is itself a statement.
Now generalize this to any other syntactic category, e.g.,
expressions. We want something that, depending on a condition
expression, behaves as one of two expressions. Therefore it must
itself be an expression. The parts of this expression will be
the condition expression and two other expressions. Not wanting
to waste more keywords, the solution chosen in C and inherited in
many later languages is:
conditionExpression ? conditinoalExpression1 : conditionalExpression2
It works for expressions just as "if" does for statements (except that
expressions must have a value, so you can't omit the "else" branch,
where the empty statement is a valid default for the "if" statement).
It's very convenient for your fingers for simple assingments (but
doesn't affect anyhow on the code performance).
True. It affects readability. Long, convoluted conditions should
probably not be put into one expression, whereas short, simple
ones should not be expanded into a multiline "if". But there are
no hard rules.
The sample you demonstrated is a bit odd from the common programming
practice, because normally (this is what I suggest to you) the
comparing element always goes to the left, and the comparison template
goes to the right. So it should be:
x.style.display = (x.style.display=='none')? '' : 'none';
Religious wars have been started over less
There is a school that encourages that it be written
'none' == x.style.display
because it prevents accidentally leaving out one of the "="'s and
still having a valid expression (an assignment even, debugging it is
*so* fun).
I'm not of that school, and I find much easier to read it the way you
suggest, but then again, I usually use Java where only boolean
expressions are allowed as condition expressions. In C and Javascript,
it's much easier to have the bug go undetected.
if (x.style.display == 'none') {
x.style.display == '';
} ....
which is now (in any shall perform form) is a proper JavaScript code,
but wrong from the DOM side; because we have two 'display' property,
and empty string is not one of them: "none" and "block";
Actually, there are plenty of valid values for the display property
("none","block","inline","table-row","table-cell", ...).
So bringing your 2nd sample to the conventional form we have:
x.style.display = (x.style.display == 'none')? 'block' : 'none';
This would fail if "x" refers to a table row, where "block" is not a
valid display type - except in IE, where it is the only one that
works. To avoid the problem of deciding whether you are running in
a mondern browser or in IE, assigning the empty string does just
what you want.
Setting a property of a style object to the empty string is generally
implemented as equivalent to doing style.removeProperty("propertyName").
This is consistent with the W3C DOM 2 Style CSS specification, which
says that reading the value of an unassigned property gives the empty
string.
Removing the property is exactly what is wanted in this case, as that
will make the default value be used, whether it is "block" or
"table-row".
/L