242

I've always had to put null in the else conditions that don't have anything. Is there a way around it?

For example,

condition ? x = true : null;

Basically, is there a way to do the following?

condition ? x = true;

Now it shows up as a syntax error.

FYI, here is some real example code:

!defaults.slideshowWidth ? defaults.slideshowWidth = obj.find('img').width()+'px' : null;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Oscar Godson
  • 31,662
  • 41
  • 121
  • 201
  • 31
    use of a ternary like `condition ? x = true : null;` should probably be written as `x = (condition ? true : null);`. As an aside, in javascript `null` evaluates to false so in THIS case you could `x = (condition);` and achieve the same result. – Matt S May 28 '10 at 21:54
  • 4
    matt, your answer is best, but it's not an answer, it's a comment! – Cheeso May 28 '10 at 21:57
  • Matt, my ACTUAL code is: !defaults.slideshowWidth ? defaults.slideshowWidth = obj.find('img').width()+'px' : null ; a shorter, better way to write that? – Oscar Godson May 28 '10 at 22:06
  • 3
    defaults.slideshowWidth = defaults.slideshowWidth || obj.find('img').width()+'px' ; – kennebec May 29 '10 at 02:51
  • it would be better to avoid the identity assignment, so this should just be a condition: `if (!defaults.slideshowWidth) defaults.slideshowWidth = obj.find('img').width()+'px'` – Mihail Malostanidis Sep 07 '18 at 11:23
  • But the name `defaults` strongly suggests that you shouldn't be mutating it here, so I suggest `const actualWidth = defaults.slideshowWidth || obj.find('img').width()+'px'`. Also, be careful if `slideshowWidth` might be an explicit 0, as that's falsy. – Mihail Malostanidis Sep 07 '18 at 11:26
  • please add the value of `x` before the condition check takes place. – Nina Scholz Mar 20 '19 at 13:47
  • @Cheeso `x = (condition ? true : null);` will assign `null` value to the `x` if the condition is not satisfied. That's not expected generally. – Gibin Ealias Jan 15 '20 at 15:14

13 Answers13

353

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 = true returns 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';
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sean Kinsey
  • 37,689
  • 7
  • 52
  • 71
  • 8
    brilliant SO, not allowing edit to correct `i/else` typo as it's not enough characters. – dewd Apr 13 '15 at 09:31
  • 1
    void(condition && x = true) - this looks great but seem to throw "invalid assignment left-hand side" error – Eugene Tiurin Sep 30 '15 at 09:51
  • 1
    void(condition && (x = true) ) // keeps the assignment separate from the first value – diamondsea Mar 06 '16 at 04:36
  • 7
    However, this is not intuitive to read, especially for developers not used to this style. You could just as easily and more readably write this as: if (condition) { x=true; } – diamondsea Mar 06 '16 at 04:40
  • 3
    Could you elaborate on *why* precisely a conditional ternary operator should only be used when its resulting value is assigned to your variable? I refer to point one of your list. The intention is understandable, but I would like to know if there is a specific reason not to use the ternary operator when the returned value is unused, such as performance, safety or something else. – Koenigsberg Jan 03 '18 at 14:09
  • 5
    Could you explain what do you mean by "might not pass validation"? I don't understand why one should wrap the expression in `void()`. thanks. – gilad905 Feb 02 '18 at 11:19
32

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'; }
In silico
  • 51,091
  • 10
  • 150
  • 143
  • 1
    You can, but you shouldn't. Atleast not without curly brackets around it - it's very errorprone. – Konerak May 28 '10 at 21:54
  • 1
    is that true? I understood the main reason for requiring curlies is because they make jslint's life easier. – Cheeso May 28 '10 at 21:56
  • 1
    @Cheeso it's errorprone in the sense of refactoring. YOu come back to add more to do in the case of a true condition without realizing there's no curly braces there. The new code will always execute rather than the case of when true. – Matt S May 28 '10 at 22:00
  • No i know, i just like writing conditionals without extras such as if(){}else{} when its equal to simply ?:; – Oscar Godson May 28 '10 at 22:05
  • like i said, i know how to do a normal If/else conditional :) im asking if it was possible with a ternary, but it looks like not, thanks! – Oscar Godson May 28 '10 at 22:19
  • 4
    Honestly, I've never known developers more scared of using a language than Javascript :-P I wouldn't like someone telling me that I shouldn't use curly braces. I omit them a lot and never have any more trouble than I would accidentally missing a brace. – Andy E May 28 '10 at 22:22
  • @mdma How is it sidestepped? I made it clear that you can't have a two-operand ternary operator. – In silico May 29 '10 at 00:01
  • I think he means you didn't give an option other than if/else, which is fine, but I think mdma was looking more for (which some others gave): defaults.slideshowWidth = defaults.slideshowWidth || obj.find('img').width()+'px' ; – Oscar Godson Jun 01 '10 at 15:52
  • Agree with @AndyE, the idea of being worried that one might come back to add more clauses only to find the lack of curly brackets causes an error: you get these developer anxieties far more, the further away from machine code your language is. Best way to reduce such anxiety is to start coding in assembly, then come back to Javascript. – hazymat Feb 26 '23 at 05:16
18

More often, people use logical operators to shorten the statement syntax:

!defaults.slideshowWidth &&
  (defaults.slideshowWidth = obj.find('img').width() + 'px');

But in your particular case the syntax can be even simpler:

defaults.slideshowWidth = defaults.slideshowWidth || obj.find('img').width() + 'px';

This code will return the defaults.slideshowWidth value if the defaults.slideshowWidth is evaluated to true and obj.find('img').width() + 'px' value otherwise.

See Short-Circuit Evaluation of logical operators for details.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Eugene Tiurin
  • 4,019
  • 4
  • 33
  • 32
14
var x = condition || null;
philfreo
  • 41,941
  • 26
  • 128
  • 141
  • 2
    `(defaults.slideshowWidth) || (defaults.slideshowWidth = obj.find('img').width()+'px')` or `defaults.slideshowWidth = defaults.slideshowWidth || (obj.find('img').width()+'px')` – Casey Chu May 29 '10 at 02:13
  • > Returns expr1 if it can be converted to true; otherwise, returns expr2. [Logical Operators (MDN)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators#Description) – Szabolcs Páll Sep 30 '15 at 10:00
11

We also have now the "Nullish coalescing operator" (??). It works similar to the "OR" operator, but only returns the left expression if it's null or undefined, it doesn't return it for the other falsy values.

Example:

const color = undefined ?? 'black';   // color: 'black'
const color = '' ?? 'black';   // color: ''
const color = '#ABABAB' ?? 'black';   // color: '#ABABAB'
Clom
  • 331
  • 2
  • 7
10

You could write

x = condition ? true : x;

So that x is unmodified when the condition is false.

This then is equivalent to

if (condition) x = true

EDIT:

!defaults.slideshowWidth 
      ? defaults.slideshowWidth = obj.find('img').width()+'px' 
      : null 

There are a couple of alternatives - I'm not saying these are better/worse - merely alternatives

Passing in null as the third parameter works because the existing value is null. If you refactor and change the condition, then there is a danger that this is no longer true. Passing in the exising value as the 2nd choice in the ternary guards against this:

!defaults.slideshowWidth = 
      ? defaults.slideshowWidth = obj.find('img').width()+'px' 
      : defaults.slideshowwidth 

Safer, but perhaps not as nice to look at, and more typing. In practice, I'd probably write

defaults.slideshowWidth = defaults.slideshowWidth 
               || obj.find('img').width()+'px'
mdma
  • 56,943
  • 12
  • 94
  • 128
  • Some live code is (anyways to get rid of the null in this?): !defaults.slideshowWidth ? defaults.slideshowWidth = obj.find('img').width()+'px' : null ; – Oscar Godson May 28 '10 at 22:09
3

What about simply

    if (condition) { code if condition = true };
Yandiro
  • 139
  • 1
  • 1
  • 11
3

To use a ternary operator without else inside of an array or object declaration, you can use the ES6 spread operator, ...():

const cond = false;
const arr = [
  ...(cond ? ['a'] : []),
  'b',
];
    // ['b']

And for objects:

const cond = false;
const obj = {
  ...(cond ? {a: 1} : {}),
  b: 2,
};
    // {b: 2}

Original source

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
fogx
  • 1,749
  • 2
  • 16
  • 38
3

You might consider using a guard expression instead (see Michael Thiessen's excellent article for more).

Let x be a logical expression, that you want to test, and z be the value you want to return, when x is true. You can then write:

y == x && z

If x is true, y evaluates to z. And if x is false, so is y.

Adam
  • 2,137
  • 16
  • 29
2

In your case i see the ternary operator as redundant. You could assign the variable directly to the expression, using ||, && operators.

!defaults.slideshowWidth ? defaults.slideshowWidth = obj.find('img').width()+'px' : null ;

will become :

defaults.slideshowWidth = defaults.slideshowWidth || obj.find('img').width()+'px';

It's more clear, it's more "javascript" style.

Krasimir Kirilov
  • 485
  • 2
  • 5
  • 14
1

The simple way to do this is:

if (y == x) z;
Adam
  • 2,137
  • 16
  • 29
0

Why not writing a function to avoid the else condition?

Here is an example:

const when = (statement, text) => (statement) ? text : null;

const math = when(1 + 2 === 3, 'Math is correct');
const obj = when(typeof "Hello Word" === 'number', "Object is a string");

console.log(math);
console.log(obj);

You could also implement that function for any objects. Here is an example for the type string:

const when = (statement, text) => (statement) ? text : null;

String.prototype.if = when;

const msg = 'Hello World!';
const givenMsg = msg.if(msg.length > 0, 'There is a message! Yayyy!');
console.log(givenMsg);
Reza Saadati
  • 5,018
  • 4
  • 27
  • 64
-1

Technically, it can return anything. But, I would say for a one liner the Ternary is easier to type and at least 1 character shorter, so therefore faster.

passTest?hasDriversLicense=true:0
if(passTest)hasDriversLicense=true
  • "*so therefore faster*" - that doesn't follow – Bergi Jul 01 '22 at 21:14
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/32154673) – Besworks Jul 06 '22 at 21:14