I was reading about the ternary operator in different languages, and noticed something interesting in the Javascript section. http://en.wikipedia.org/wiki/%3F:#JavaScript
The conditional operator in JavaScript has the same syntax and precedence structure as in the other BCPL-derived variants, but a significant difference exists in the semantics: it returns an l-value.
The first sentence states that the return of the ternary in javascript is an lvalue, so I tried some examples, with odd results (in the chrome console).
Given:
var a = { 'yo' : 'momma' }
var b = { 'yo' : 'cool' }
var bool = true
(bool? a : b).yo = 'LLJ'
//a is now { 'yo' : 'LLJ' }
(bool? a.yo : b.yo) = 'LLJ' //throws a reference error
Why does the first work and the second fail? (Logically they're the same statements, no?)
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)