# PBS 13 of X – JS Conditionals

In the previous instalment we got our first taste of JavaScript. We learned about variables, literal data types, and some basic string and arithmetic operators. In this instalment we’re going to focus on booleans. We’ll look at how non-boolean values get converted to booleans when needed (e.g. is `'boogers'`

`true`

or `false`

?). We’ll learn about some comparison operators that result in boolean values. We’ll learn about some logical operators. At that stage we’ll have all the knowledge we need to learn about our third fundamental programming concept – branching.

## Matching Podcast Episode 434

Listen Along: Chit Chat Across the Pond Episode 434

You can also Download the MP3

## Our New Playground

As with the previous instalment, we’ll be working in our JavaScript playground. However, since the last instalment, the playground has gotten a bit of an upgrade. No more popup windows, so it now works on tablet devices as well as traditional computers.

The basic operation remains the same, but now when you click `Run`

, the output will appear at the bottom of the page instead of in a new window.

You can download this code for this updated playground here or here on GitHub, or you can use the online version at www.bartb.ie/pbsdemos/pbs-JavaScriptPlayground/.

## Boolean Conversions

When needed, JavaScript can convert any value to a boolean, i.e. to `true`

or `false`

. It’s important to understand the *truthiness* of values.

All numbers, with the exception of zero and `NaN`

, evaluate to `true`

, including the negative numbers.

All strings with the exception of the empty string evaluate to `true`

.

The special values `undefined`

and `null`

evaluate to `false`

. (`null`

is a literal value that can be used when you want a variable to be defined, but not hold a real value).

As you can see, the vast majority of values convert to `true`

. So my advice is to remember that the following convert to `false`

: `undefined`

, `null`

, `0`

, `NaN`

, and `''`

(the empty string).

A little gotcha here is that the string `'false'`

evaluates to `true`

!

```
pbs.say("0 is\t\t\t" + Boolean(0));
pbs.say("1 is\t\t\t" + Boolean(1));
pbs.say("-2.6 is\t\t\t" + Boolean(-2.6));
pbs.say("3.1416 is\t\t" + Boolean(3.1416));
pbs.say("NaN is\t\t\t" + Boolean(NaN));
pbs.say("null is\t\t\t" + Boolean(null));
pbs.say("undefined is\t\t" + Boolean(undefined));
pbs.say("'' (empty string) is\t" + Boolean(''));
pbs.say("'true' is\t\t" + Boolean('true'));
pbs.say("'false' is\t\t" + Boolean('false'));
pbs.say("'boogers' is\t\t" + Boolean('boogers'));
pbs.say("' ' (space) is\t\t" + Boolean(' '));
```

## Comparison Operators

JavaScript supports a number of operators for comparing values. What all these operators have in common is that they evaluate to a boolean value – a comparison is either `true`

, or `false`

.

### Equality

Let’s start with equality, which is not as simple as you might think.

The `===`

operator checks for exact equality. It’s very strict – `true`

is only returned if the two values are identical – same type and all. This is why I suggest you get into the habit of referring to this operator as *is exactly equal to*. This strict equality check has some implications that you may find counterintuitive:

```
pbs.say("4 === 4 is\t\t" + (4 === 4));
pbs.say("'4' === '4' is\t\t" + ('4' === '4'));
pbs.say("'4' === 4 is\t\t" + ('4' === 4));
pbs.say("true === true is\t" + (true === true));
pbs.say("'true' === 'true' is\t" + ('true' === 'true'));
pbs.say("'true' === true is\t" + ('true' === true));
pbs.say("true === 1 is\t\t" + (true === 1));
pbs.say("NaN === NaN is\t\t" + (NaN === NaN));
```

Notice that `NaN`

is not considered to be exactly equal to `NaN`

.

In many situations, most in fact, this level of equality checking is simply too precise. In the general case, we probably do want the string `'4'`

to be considered equal to the number `4`

. This is where the `==`

operator comes in.

`==`

is a more liberal equality operator that does type conversions before comparing values. My advice is to think of this operator as *is effectively equal to*.

By default, the `==`

operator works in numeric mode, converting the values to numbers as needed before doing the comparison. However, in the case where both values are strings, a string comparison is performed instead. This simple rule results in behaviour that is almost always sensible, as demonstrated by the example below:

```
pbs.say("4 == 4 is\t\t" + (4 == 4));
pbs.say("'4' == '4' is\t\t" + ('4' == '4'));
pbs.say("'4' == 4 is\t\t" + ('4' == 4));
pbs.say("true == true is\t\t" + (true == true));
pbs.say("'true' == 'true' is\t" + ('true' == 'true'));
pbs.say("'true' == true is\t" + ('true' == true));
pbs.say("true == 1 is\t\t" + (true == 1));
pbs.say("NaN == NaN is\t\t" + (NaN == NaN));
```

However, all is not perfectly logical – again, notice that `NaN`

is not considered to be effectively equal to `NaN`

.

The other outlier in the example above is `'true' == true`

. The value on both sides is not a string, so the operator works numerically – `true`

is converted to `1`

, and `'true'`

to `NaN`

, hence, the result of the comparison is `false`

.

I’m repeating myself here, but I think it’s important to hammer home the importance of keeping `=`

, `==`

, and `===`

straight in your head. To that end, I strongly suggest you develop the habit of mentally reading these three operators as follows:

`=`

*is assigned the value of*`==`

*is effectively equal to*`===`

*is exactly equal to*

### Comparisons

As well as checking for equality as described above, JavaScript also supports the following comparison operators:

`<`

*is less than*`>`

*is greater than*`<=`

*is less than or equal to*`>=`

*is greater than or equal to*

Just like `==`

, these operators work in one of two modes – *numerically* or *lexically* (alphabetic comparisons).

The default behaviour is to convert the values on both sides of the operator to numbers and compare them mathematically. Any comparison to `NaN`

evaluates to `false`

.

Only when **both** of the values are strings do the operators switch to lexical mode – that is to say, comparing the values alphabetically. One string is less than another if it would appear in the dictionary before the other.

```
pbs.say("2 < 4 is\t\t" + (2 < 4));
pbs.say("'2' < 4 is\t\t" + ('2' < 4));
pbs.say("4 < 4 is\t\t" + (4 < 4));
pbs.say("'boogers' < 'nose' is\t" + ('boogers' < 'nose'));
pbs.say("'boogers' > 'nose' is\t" + ('boogers' > 'nose'));
pbs.say("'boogers' < 4 is\t" + ('boogers' < 4));
pbs.say("'boogers' > 4 is\t" + ('boogers' > 4));
pbs.say("'12' < '4' is\t\t" + ('12' < '4'));
pbs.say("2 <= 4 is\t\t" + (2 <= 4));
pbs.say("'2' <= 4 is\t\t" + ('2' <= 4));
pbs.say("4 <= 4 is\t\t" + (4 <= 4));
pbs.say("NaN < NaN is\t\t" + (NaN < NaN));
pbs.say("NaN > NaN is\t\t" + (NaN > NaN));
pbs.say("NaN <= NaN is\t\t" + (NaN <= NaN));
pbs.say("NaN >= NaN is\t\t" + (NaN >= NaN));
```

## Logical Operators

The logical operators work on booleans, so all values they operate on get converted to booleans before the operator is applied, and, the outcome is always a boolean. There are just three logical operators:

`&&`

- A logical AND – only evaluates to
`true`

when both values are`true`

`||`

- A logical OR – evaluates to
`true`

when one or both values are`true`

`!`

- A logical NOT – this is a unary operator that inverts the value it’s applied to – it should be placed in front of the value to be inverted

In terms of precedence, `!`

has the highest precedence, then `&&`

, and finally `||`

.

```
pbs.say('false && false is\t' + (false && false));
pbs.say('false && true is\t' + (false && true));
pbs.say('true && false is\t' + (true && false));
pbs.say('true && true is\t\t' + (true && true));
pbs.say('');
pbs.say('false || false is\t' + (false || false));
pbs.say('false || true is\t' + (false || true));
pbs.say('true || false is\t' + (true || false));
pbs.say('true || true is\t\t' + (true || true));
pbs.say('');
pbs.say('!false is\t\t' + (!false));
pbs.say('!true is\t\t' + (!true));
```

## Playground Inputs

Before we look at branching, let’s look at how to read values out of the input fields in our playground.

You can read the value from the first input with `pbs.input(1)`

, the second with `pbs.input(2)`

, and the third with `pbs.input(3)`

.

Because of how HTML text fields work, the value returned by `pbs.input()`

is always a string. This means that you need to explicitly convert to a number before doing arithmetic or making numeric comparisons.

```
pbs.say(parseInt(pbs.input(1)) + parseInt(pbs.input(2)));
```

## Branching – the `if`

Statement

Up until now all our mini examples have just been a series of statements that get executed one after the other in the order they appear in the script. Every line always gets executed. The path through the code is always the same.

Branching is the act of altering the path through code depending on some condition. If this condition is met, do this, otherwise, do that.

JavaScript implements this concept with the `if`

statement. An `if`

statement takes the following form:

```
if(condition) statement_1; else statement_2;
```

If the `condition`

evaluates to `true`

, then `statement_1`

will execute, otherwise, `statement_2`

will execute. The `else`

part is optional. If you omit it, and the `condition`

evaluates to `false`

, `statement_1`

is simply skipped.

The following two coding styles are entirely in keeping with the spec:

```
if(parseInt(pbs.input(1)) % 2 == 0) pbs.say('EVEN');
else pbs.say('ODD');
```

```
if(parseInt(pbs.input(1)) % 2 == 0)
pbs.say('EVEN');
else
pbs.say('ODD');
```

You **can** write code like this, but **please don’t**! Develop the good habit now of always using code blocks in `if`

statements. That is to say, wrap the statement(s) in curly braces. This will allow you to execute multiple statements on `true`

or `false`

evaluation instead of just one. Also it will protect you from a whole class of subtle but very dangerous bugs creeping into your code. Had Apple’s developers followed this simply piece of advice, the famous GO TO FAIL bug would never have happened!

This is how you should write your `if`

statements, even when you only want to execute one statement on `true`

and/or `false`

evaluation of the condition:

```
if(parseInt(pbs.input(1)) % 2 == 0){
pbs.say('EVEN');
}else{
pbs.say('ODD');
}
```

This is also a good time to mention code layout again. It’s universally agreed that code blocks should be indented, so that you can easily see where the `if`

and `else`

parts begin and end. What’s nowhere near universally agreed on is where the curly braces should go. What you see above is my preferred style – a variant of the K&R style.

Some people prefer to have the braces on new lines, the so-called *Allman style* (AKA *BSD style*), like so:

```
if(parseInt(pbs.input(1)) % 2 == 0)
{
pbs.say('EVEN');
}
else
{
pbs.say('ODD');
}
```

There are also more or less *cuddled* variants to all these styles, that is to say, more or less optional white space included. The canonical K&R style is less cuddled than what I use (has more white space):

```
if ( parseInt( pbs.input( 1 ) ) % 2 == 0 ) {
pbs.say( 'EVEN' );
} else {
pbs.say( 'ODD' );
}
```

There is no right answer – pick one, and be consistent!

All examples in this series will use the style I prefer – a cuddled variant of K&R.

## Checking for `NaN`

We have one more new thing to learn before we can move on to our final example for this instalment. We need to learn about the built-in JavaScript function for checking if a value is not a number. The function is very well named – `isNaN()`

. It behaves pretty much as you would expect:

```
pbs.say("isNaN(4) returns " + isNaN(4));
pbs.say("isNaN(3.14159) returns " + isNaN(3.14159));
pbs.say("isNaN(-2.6) returns " + isNaN(-2.6));
pbs.say("isNaN(-2.6e3) returns " + isNaN(-2.6e3));
pbs.say("isNaN('6') returns " + isNaN('6'));
pbs.say("isNaN('boogers') returns " + isNaN('boogers'));
pbs.say("isNaN(true) returns " + isNaN(true));
pbs.say("isNaN(NaN) returns " + isNaN(NaN));
```

## Worked Example

As a final example to tie everything together, let’s write a more robust odd/even checker than the one in the examples above.

We’ll need to take our input from the first input text box, make sure it’s a number, and then check whether it’s odd or even.

```
// get the input and convert to an integer
var rawInput = pbs.input(1);
var inputNum = parseInt(rawInput);
// validate the input and proceed accordingly
if(isNaN(inputNum)){
// not a number, so print an error
pbs.say("'" + rawInput + "' is not a number, so it's neither ODD nor EVEN");
}else{
// the input is a number, so test for eveness
var ans = inputNum + ' is ';
if(inputNum % 2 == 0){
ans += 'EVEN';
}else{
ans += 'ODD';
}
// print the answer
pbs.say(ans);
}
```

## Conclusions

We have now learned about three core concepts all programming languages share – variables, operators, and branching. In the next instalment we’ll learn about two more core concepts – arrays and loops. This will give us the ability to store lists of values and to process them.