First of all, a ternary expression is not a replacement for an if/else construct - it's an equivalent to an if/else construct that returns a value. That is, an if/else clause is code, a ternary expression is an expression, meaning that it returns a value.
This means several things:
- use ternary expressions only when you have a variable on the left side of the
=that is to be assigned the return value - only use ternary expressions when the returned value is to be one of two values (or use nested expressions if that is fitting)
- each part of the expression (after ? and after : ) should return a value without side effects (the expression
x = truereturns true as all expressions return the last value, but it also changes x without x having any effect on the returned value)
In short - the 'correct' use of a ternary expression is
var resultofexpression = conditionasboolean ? truepart: falsepart;
Instead of your example condition ? x=true : null ;, where you use a ternary expression to set the value of x, you can use this:
condition && (x = true);
This is still an expression and might therefore not pass validation, so an even better approach would be
void(condition && x = true);
The last one will pass validation.
But then again, if the expected value is a boolean, just use the result of the condition expression itself
var x = (condition); // var x = (foo == "bar");
UPDATE
In relation to your sample, this is probably more appropriate:
defaults.slideshowWidth = defaults.slideshowWidth || obj.find('img').width()+'px';
Answer from Sean Kinsey on Stack OverflowFirst of all, a ternary expression is not a replacement for an if/else construct - it's an equivalent to an if/else construct that returns a value. That is, an if/else clause is code, a ternary expression is an expression, meaning that it returns a value.
This means several things:
- use ternary expressions only when you have a variable on the left side of the
=that is to be assigned the return value - only use ternary expressions when the returned value is to be one of two values (or use nested expressions if that is fitting)
- each part of the expression (after ? and after : ) should return a value without side effects (the expression
x = truereturns true as all expressions return the last value, but it also changes x without x having any effect on the returned value)
In short - the 'correct' use of a ternary expression is
var resultofexpression = conditionasboolean ? truepart: falsepart;
Instead of your example condition ? x=true : null ;, where you use a ternary expression to set the value of x, you can use this:
condition && (x = true);
This is still an expression and might therefore not pass validation, so an even better approach would be
void(condition && x = true);
The last one will pass validation.
But then again, if the expected value is a boolean, just use the result of the condition expression itself
var x = (condition); // var x = (foo == "bar");
UPDATE
In relation to your sample, this is probably more appropriate:
defaults.slideshowWidth = defaults.slideshowWidth || obj.find('img').width()+'px';
No, it needs three operands. That's why they're called ternary operators.
However, for what you have as your example, you can do this:
if(condition) x = true;
Although it's safer to have braces if you need to add more than one statement in the future:
if(condition) { x = true; }
Edit: Now that you mention the actual code in which your question applies to:
if(!defaults.slideshowWidth)
{ defaults.slideshowWidth = obj.find('img').width()+'px'; }
I have scoured StackOverflow regarding this issue and the suggested solution seems to be to use the && operator instead of a ternary statement like so condition && (x = true); , however this doesn't work when I use it in my code:
let a = false b = a && 3 console.log(b)
This logs false instead of undefined which is what I expected since a is false.
Videos
Generally speaking, the conditional operator is intended to make an if statement with a value. w = x ? y : z. Thus, if you're using it for side effects, it's counter-intuitive. Valid, but counter-intuitive; and remember that you're writing code for your teammates to read.
A couple of cases, that are not assignments, where I find ternary operators useful are:
In function arguments: in my opinion
f( e1, .. cond ? em : dm, .. en);
is less error prone than
if ( cond) f( e1, .. em, .. en); else f( e1, .. dm, .. en);
When you want to call one function or another with identical arguments: again I find
(cond ? f : g)( /* long and complex argument list */);
less error prone than
if ( cond) f( /* long and complex argument list */);
else g( /* long and complex argument list */);
As I see it the key thing in each case is that the ? form has less repetition. Repetition opens up the possibility of changing one instance and forgetting to change the other.
Personally I find the best way to do this is still the good old if statement:
var value = someArray.indexOf(3);
if (value === -1) {
value = 0;
}
Code should be readable, so being succinct should not mean being terse whatever the cost - for that you should repost to https://codegolf.stackexchange.com/ - so instead I would recommend using a second local variable named index to maximize reading comprehensibility (with minimal runtime cost too, I note):
var index = someArray.indexOf( 3 );
var value = index == -1 ? 0 : index;
But if you really want to cut this expression down, because you're a cruel sadist to your coworkers or project collaborators, then here are 4 approaches you could use:
1: Temporary variable in a var statement
You can use the var statement's ability to define (and assign) a second temporary variable index when separated with commas:
var index = someArray.indexOf(3), value = index !== -1 ? index: 0;
2: Immediately-Invoked Function Expression (IIFE)
Another option is an anonymous function which is invoked immediately after it’s defined:
// Traditional syntax:
var value = function( x ) { return x !== -1 ? x : 0 }( someArray.indexOf(3) );
// ES6 syntax:
var value = ( x => x !== -1 ? x : 0 )( someArray.indexOf(3) );
3: Comma operator
There is also the infamous "comma operator" which JavaScript supports, which is also present in C and C++.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator
You can use the comma operator when you want to include multiple expressions in a location that requires a single expression.
You can use it to introduce side-effects, in this case by reassigning to value:
var value = ( value = someArray.indexOf(3), value !== -1 ? value : 0 );
This works because var value is interpreted first (as it's a statement), and then the left-most, inner-most value assignment, and then the right-hand of the comma operator, and then the ternary operator - all legal JavaScript.
4: Re-assign in a subexpression
Commentator @IllusiveBrian pointed out that the use of the comma-operator (in the previous example) is unneeded if the assignment to value is used as a parenthesized subexpression:
var value = ( ( value = someArray.indexOf(3) ) !== -1 ? value : 0 );
Note that the use of negatives in logical expressions can be harder for humans to follow - so all of the above examples can be simplified for reading by changing idx !== -1 ? x : y to idx == -1 ? y : x - or idx < 0 ? y : x.
var value = ( ( value = someArray.indexOf(3) ) == -1 ? 0 : value );
This is a one-line shorthand for an if-else statement. It's called the conditional operator.1
Here is an example of code that could be shortened with the conditional operator:
var userType;
if (userIsYoungerThan18) {
userType = "Minor";
} else {
userType = "Adult";
}
if (userIsYoungerThan21) {
serveDrink("Grape Juice");
} else {
serveDrink("Wine");
}
This can be shortened with the ?: like so:
var userType = userIsYoungerThan18 ? "Minor" : "Adult";
serveDrink(userIsYoungerThan21 ? "Grape Juice" : "Wine");
Like all expressions, the conditional operator can also be used as a standalone statement with side-effects, though this is unusual outside of minification:
userIsYoungerThan21 ? serveGrapeJuice() : serveWine();
They can even be chained:
serveDrink(userIsYoungerThan4 ? 'Milk' : userIsYoungerThan21 ? 'Grape Juice' : 'Wine');
Be careful, though, or you will end up with convoluted code like this:
var k = a ? (b ? (c ? d : e) : (d ? e : f)) : f ? (g ? h : i) : j;
1 Often called "the ternary operator," but in fact it's just a ternary operator [an operator accepting three operands]. It's the only one JavaScript currently has, though.
I want to add some to the given answers.
In case you encounter (or want to use) a ternary in a situation like 'display a variable if it's set, else...', you can make it even shorter, without a ternary.
Instead of:
var welcomeMessage = 'Hello ' + (username ? username : 'guest');
You can use:
var welcomeMessage = 'Hello ' + (username || 'guest');
This is Javascripts equivallent of PHP's shorthand ternary operator ?:
Or even:
var welcomeMessage = 'Hello ' + (username || something || maybethis || 'guest');
It evaluates the variable, and if it's false or unset, it goes on to the next.