100

I am using jQuery 1.7.1

I am just starting to use the JavaScript ternary operator to replace simple if/else statements. I have done so successfully in several places. I was surprised when I successfully made something else work when I thought for sure it wouldn't, but I tried anyway.

Here's the original statement:

function updateItem() {
    $this = $(this);
    var IsChecked = $this.hasClass("IsChecked");
    if (IsChecked == true){
        removeItem($this);
    } else {
        addItem($this);
    }
}

Here's the same function using the ternary operator:

function updateItem() {
    $this = $(this);
    var IsChecked = $this.hasClass("IsChecked");
    (IsChecked == true) ? removeItem($this) : addItem($this);
}

I was surprised because all of the examples I saw being used were merely setting variables like this:

x = (1 < 2) ? true : false;

My question is whether this is "normal" use and will it work in most versions of JavaScript? Where will it fail? Are there other less obvious uses for it?

UPDATE -- Thanks for the "real world" advice!!!

I am using this as my function:

function updateItem() {
    $this = $(this);
    $this.hasClass("IsChecked") ? removeItem($this) : addItem($this);
}
Evik James
  • 10,335
  • 18
  • 71
  • 122
  • It is normal and It will work just fine.. In general, readability is hard when using ternary operators but in your case it looks just fine. – Selvakumar Arumugam Apr 25 '12 at 21:12
  • 1
    Hmm.... you could also do this since they both accept the same arguments `(IsChecked ? removeItem : addItem)($this)`. However, to answer your question, yes this is normal and there is nothing wrong with using ternary operators as long as they don't detract from maintainability or readability in a situation where that is needed. http://jsfiddle.net/vsB3f/ – Kevin B Apr 25 '12 at 21:18
  • `if($this.hasClass("IsChecked")) removeItem($this); else addItem($this)` is the proper way. The ternary operator is not meant for cases like this but for things like `foo(isChecked ? 'bar' : meow());` (i.e. when you care about the "return value" of whatever you do in the then/else blocks) – ThiefMaster Apr 25 '12 at 21:25
  • 2
    In your example, skip the first line in favor of this: `$(this).hasClass("IsChecked") ? removeItem($this) : addItem($this);` I can understand your code as-is on one line, so it fits my rule of thumb (see post below). Works for me. – Surreal Dreams Apr 25 '12 at 21:35
  • 1
    Possible duplicate of [using ternary operator in javascript to invoke two functions?](http://stackoverflow.com/questions/1655037/using-ternary-operator-in-javascript-to-invoke-two-functions) – Cees Timmerman Dec 01 '15 at 16:01
  • I feel like I have to add this, even if it's weird, because I do it a lot: (isChecked ? removeItem : addItem)($this). – Sprague Apr 06 '16 at 09:49

6 Answers6

198

Heh, there are some pretty exciting uses of ternary syntax in your question; I like the last one the best...

x = (1 < 2) ? true : false;

The use of ternary here is totally unnecessary - you could simply write

x = (1 < 2);

Likewise, the condition element of a ternary statement is always evaluated as a Boolean value, and therefore you can express:

(IsChecked == true) ? removeItem($this) : addItem($this);

Simply as:

(IsChecked) ? removeItem($this) : addItem($this);

In fact, I would also remove the IsChecked temporary as well which leaves you with:

($this.hasClass("IsChecked")) ? removeItem($this) : addItem($this);

As for whether this is acceptable syntax, it sure is! It's a great way to reduce four lines of code into one without impacting readability. The only word of advice I would give you is to avoid nesting multiple ternary statements on the same line (that way lies madness!)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
JonnyReeves
  • 6,119
  • 2
  • 26
  • 28
  • note that you may want to avoid using upper cases in class names (IsChecked becoming is-checked) http://stackoverflow.com/questions/1547986/can-i-use-camel-case-in-css-class-names – Adriano Jul 07 '14 at 08:42
  • 1
    JS has first class functions: `($this.hasClass("isChecked") ? removeItem : addItem)($this)` – ClojureMostly May 20 '17 at 15:15
  • "_the condition element of a ternary statement is always evaluated as a Boolean value_" Nope, ternary operator checks the truth value of the condition, the value of the expression in the condition is evaluated and returned as it is, it's not converted or evaluated to a boolean. Additionally, the example is poor, you should not use ternary operator to replace a statement (if ..else in this case), the operator returns a value, which should be used. – Teemu Oct 07 '22 at 06:41
24

The ternary style is generally used to save space. Semantically, they are identical. I prefer to go with the full if/then/else syntax because I don't like to sacrifice readability - I'm old-school and I prefer my braces.

The full if/then/else format is used for pretty much everything. It's especially popular if you get into larger blocks of code in each branch, you have a muti-branched if/else tree, or multiple else/ifs in a long string.

The ternary operator is common when you're assigning a value to a variable based on a simple condition or you are making multiple decisions with very brief outcomes. The example you cite actually doesn't make sense, because the expression will evaluate to one of the two values without any extra logic.

Good ideas:

this > that ? alert(this) : alert(that);  //nice and short, little loss of meaning

if(expression)  //longer blocks but organized and can be grasped by humans
{
    //35 lines of code here
}
else if (something_else)
{
    //40 more lines here
}
else if (another_one)  /etc, etc
{
    ...

Less good:

this > that ? testFucntion() ? thirdFunction() ? imlost() : whathappuh() : lostinsyntax() : thisisprobablybrokennow() ? //I'm lost in my own (awful) example by now.
//Not complete... or for average humans to read.

if(this != that)  //Ternary would be done by now
{
    x = this;
}
else
}
    x = this + 2;
}

A really basic rule of thumb - can you understand the whole thing as well or better on one line? Ternary is OK. Otherwise expand it.

Surreal Dreams
  • 26,055
  • 3
  • 46
  • 61
  • Since this is an answer about style, I would highly disrecommend stringing else if after else if. Use a switch() if you have more than 1 else. Or just use multiple atomic IFs. – user1944491 Oct 13 '21 at 21:32
12

I would also like to add something from me.

Other possible syntax to call functions with the ternary operator, would be:

(condition ? fn1 : fn2)();

It can be handy if you have to pass the same list of parameters to both functions, so you have to write them only once.

(condition ? fn1 : fn2)(arg1, arg2, arg3, arg4, arg5);

You can use the ternary operator even with member function names, which I personally like very much to save space:

$('.some-element')[showThisElement ? 'addClass' : 'removeClass']('visible');

or

$('.some-element')[(showThisElement ? 'add' : 'remove') + 'Class']('visible');

Another example:

var addToEnd = true; //or false
var list = [1,2,3,4];
list[addToEnd ? 'push' : 'unshift'](5);
Liglo App
  • 3,719
  • 4
  • 30
  • 54
9

There is nothing particularly tricky about the example you posted.

In a ternary operator, the first argument (the conditional) is evaluated and if the result is true, the second argument is evaluated and returned, otherwise, the third is evaluated and returned. Each of those arguments can be any valid code block, including function calls.

Think of it this way:

var x = (1 < 2) ? true : false;

Could also be written as:

var x = (1 < 2) ? getTrueValue() : getFalseValue();

This is perfectly valid, and those functions can contain any arbitrary code, whether it is related to returning a value or not. Additionally, the results of the ternary operation don't have to be assigned to anything, just as function results do not have to be assigned to anything:

(1 < 2) ? getTrueValue() : getFalseValue();

Now simply replace those with any arbitrary functions, and you are left with something like your example:

(1 < 2) ? removeItem($this) : addItem($this);

Now your last example really doesn't need a ternary at all, as it can be written like this:

x = (1 < 2);  // x will be set to "true"
Jeff B
  • 29,943
  • 7
  • 61
  • 90
7

If you're going to nest ternary operators, I believe you'd want to do something like this:

   var audience = (countrycode == 'eu') ? 'audienceEU' :
                  (countrycode == 'jp') ? 'audienceJP' :
                  (countrycode == 'cn') ? 'audienceCN' :
                  'audienceUS';

It's a lot more efficient to write/read than:

var audience = 'audienceUS';
if countrycode == 'eu' {
   audience = 'audienceEU';
} else if countrycode == 'jp' {
   audience = 'audienceJP';
} else if countrycode == 'cn' {
   audience = 'audienceCN';
}

As with all good programming, whitespace makes everything nice for people who have to read your code after you're done with the project.

Sam W
  • 79
  • 1
  • 1
  • 7
    Strongly disagree with your above comment about nested ternary being easier to read and debug. Personally, I would rather see the nested else/if block replaced with either a [lookup table](https://coderwall.com/p/6e7rea) or a switch statement. – JonnyReeves Dec 31 '13 at 09:33
  • @JonnyReeves agreed - usually the nested ternary syntax is best used when checking different conditions (e.g. [modulo of numbers](http://twistedoakstudios.com/blog/Post5273_how-to-read-nested-ternary-operators)) – Alex Nov 04 '14 at 11:48
2

I know question is already answered.

But let me add one point here. This is not only case of true or false. See below:

var val="Do";

Var c= (val == "Do" || val == "Done")
          ? 7
          : 0

Here if val is Do or Done then c will be 7 else it will be zero. In this case c will be 7.

This is actually another perspective of this operator.

Himanshu Tiwari
  • 107
  • 1
  • 2
  • 15