SlightlyLoony
Tera Contributor

JavaScript, like all the "C-like" languages, has a conditional operator (sometimes called the ternary operator because it has three parts). If you don't know it by name, it looks like this:


<condition> ? <value> : <value>

This is one of those langauge elements that seems to have a bit of "religion" associated with it. Some developers avoid it at all costs, for stated reasons ranging from "It's confusing!" to "It's ugly!" Others seem to embrace it as the one true way. I think of it as a useful tool, mainly for simplifying and clarifying code...

If you don't know this operator, here's how it works. When JavaScript sees a conditional operator, the first thing it does is to evaluate the condition, which can be any expression at all. Whatever that expression is, JavaScript will evaluate it and then coerce it to a boolean. If the result is true, then the first value (after the question mark) is returned. If the result is false, the second value (after the colon) is returned. The key thing to remember is that the conditonal operator as a whole always returns one of the two values.

Most often the condition will be a simple comparison, like this:

var word = (words == 1) ? 'thing' : 'things';

The condition part here is (words == 1), which compares the value of the variable words to the number 1, and evaluates to either true or false — no coercion to boolean needed. If this comparison is true, then 'thing' is the result of this conditional operator, otherwise it's 'things'.

But consider this different use of the conditional operator, to handle calling a method on a value that we're not quite sure is actually an object:

var x = Something.fetch();
var result = (!!x && (typeof x == 'object')) ? x.process() : null;

That code behaves exactly like the following:

var x = Something.fetch();
var result;
if (!!x && (typeof x == 'object'))
result = x.process();
else
result = null;

Six lines of code reduced to two lines of code that easier to read. Win! This is a good example of my favorite use for the conditional operator: simplifying code.

Here's another example, showing how the values can be expressions themselves:

var x = 14;
var y = 83;
var op = 'sub';
var result = (op == 'add') ? x + y : x - y;

This is exactly the same as the following code:

var x = 14;
var y = 83;
var op = 'sub';
var result;
if (op == 'add')
result = x + y;
else
result = x - y;

The values in this case are expressions (like x - y). They can be any kind of expression or value, including objects and functions. For instance, you could (if you were a perverse developer) implement a selectable ascending or descending sort like this:

var x = [34,939,2,59,2904,495,3];
var asc = true;
x.sort(asc ? function(a,b) {return a - b;} : function(a,b) {return b - a;});

That's not the way I'd recommend implementing it, but it is an example of the values in a conditional operator being something you might not expect: in this case, a function.

I'll leave you with one last (extended) example of using conditional operators to simplify your code. If you start with this:

// return the difference between two temperatures a and b, expressed in F (type = 'F') or C (type = 'C')
// temperature values are suffixed with type, like '24C' or '94F' and may be non-integer
// result is integer temperature, and always positive
function tempDiff (a, b, type) {
var t1 = fc(parse(a));
var t2 = fc(parse(b));
var d = t1.value - t2.value;
var r = {value: d, units: 'C'};
if (type == 'F') {
r.value *= 9/5;
r.units = 'F';
}
return '' + Math.round(Math.abs(r.value)) + r.units;

function parse(t) {
return {value: t.substring(0, t.length - 1) - 0, units: t.substr(t.length - 1)};
}

function fc(t) {
if (t.units == 'C')
return t;

return {value: (t.value - 32) * 5 / 9, units: 'C'};
}
}

You could simplify it to this:

// return the difference between two temperatures a and b, expressed in F (type = 'F') or C (type = 'C')
// temperature values are suffixed with type, like '24C' or '94F' and may be non-integer
// result is integer temperature, and always positive
function tempDiff (a, b, type) {
var t1 = fc(parse(a));
var t2 = fc(parse(b));
var d = t1.value - t2.value;
return '' + Math.round(Math.abs(d * ((type == 'F') ? 9/5 : 1))) + type;

function parse(t) {
return {value: t.substring(0, t.length - 1) - 0, units: t.substr(t.length - 1)};
}

function fc(t) {
return (t.units == 'C') ? t : {value: (t.value - 32) * 5 / 9, units: 'C'};
}
}

Note that in one case (d * ((type == 'F') ? 9/5 : 1)) we had to surround the entire conditional operator with parentheses. If we had not, JavaScript would think that our condition was d * (type == 'F'), which would work very poorly 🙂

Well, that's about enough of that!