Javascript Ternary Operator lvalue
Because the second line is not referencing the value of a.yo
or b.yo
, its referencing a flat object.
The first expression ends with .yo
so it knows to reference the value of either a
or b
.
Wikipedia was wrong. The conditional operator returns an r-value, not an l-value.
The history of the article is quite interesting, so I've summarised it here:
30 August 2010: The Beginning
JavaScript section created. Correctly says that in JavaScript the ternary operator returns an r-value, but incorrectly says that in C/C++/Java it returns an l-value. Only in C++ the ternary operator returns an l-value.31 January 2011: Cannot yield an l-value in C
C correctly removed from the JavaScript section because it doesn't return an l-value. Java remains.15 February 2011: "Corrected"
The comparison to Java and C++ is removed (the comment correctly says that Java never yielded an l-value), but oh no! JavaScript suddenly returns an l-value!7 March 2011: Hope is restored...
The incorrect "l-value" is changed to "value", linking to the Value article (which describes both l-values and r-values).7 March 2011: ...but not for long
The link text is changed to say "l-value".7 September 2013: Three cheers for Qantas 94 Heavy!
Thanks to this question, Wikipedia has been corrected.
Nope (it seems that Wikipedia's reference to "l-value" is misleading) - it is returning the value of the argument, not the reference to it; values in JavaScript cannot be assigned to directly1.
If you just did the following:
console.log(bool ? a.yo : b.yo);
// like doing the following:
'string' = 'eee';
... you would get a string - you can't assign to a string value/literal. All property references are converted to their value when passed into the conditional operator.
However, with an object, the reference value is an object, and since the property of an object is a reference, it works fine.
console.log(bool ? a : b); // you get an object, it's fine
The ECMAScript specification (that's the standard version of JavaScript) says that you can't get references (i.e. a l-value) from the conditional operator:
11.12 Conditional Operator ( ? : )
- Let
lref
be the result of evaluating LogicalORExpression.- If
ToBoolean(GetValue(lref))
is true, then:
- Let
trueRef
be the result of evaluating the first AssignmentExpression.- Return
GetValue(trueRef)
.- Else
- Let
falseRef
be the result of evaluating the second AssignmentExpression.- Return
GetValue(falseRef)
.
GetValue
is an internal function that converts a reference to a value, therefore that's why you get a value, not a reference as you expected.
1: The internal assignment method in ECMAScript does not allow non-references to be assigned to:
8.7.2 PutValue (V, W)
- If
Type(V)
is not Reference, throw a ReferenceError exception.- ... (the rest is unimportant, my emphasis)