### Apr

#### 9

# PBS 13 of X – JS Conditionals

Filed Under Computers & Tech, Software Development on April 9, 2016 at 1:41 pm

- PBS 1 of X – Introduction
- PBS 2 of X – Introducing HTML
- PBS 3 of X – HTML Block Elements
- PBS 4 of X – HTML In-line Elements
- PBS 5 of X – Images & Links
- PBS 6 of X – Introducing CSS
- PBS 7 of X – More CSS
- PBS 8 of X – CSS Positioning
- PBS 9 of X – More CSS Positioning
- PBS 10 of X – Yet More CSS
- PBS 11 of X – Tables
- PBS 12 of X – Introducing JavaScript
- PBS 13 of X – JS Conditionals
- PBS 14 of X – JS Loops & Arrays
- PBS 15 of X – JS Functions
- PBS 16 of X – JS Callbacks
- PBS 17 of X – JS Objects
- PBS 18 of X – JS Miscellany
- PBS 19 of X – Some JavaScript Challenges
- PBS 20 of X – JS in the Browser
- PBS 21 of X – jQuery Basics
- PBS 22 of X – jQuery Events
- PBS 23 of x – Creating Elements with jQuery
- PBS 24 of x – Creating a JavaScript API
- PBS 25 of x – A Case Study (bartificer.linkToolkit.js)
- PBS 26 of x – HTML Data Attributes with jQuery
- PBS 27 of x – JS Prototype Revision | HTML Forms
- PBS 28 of x – JS Prototype Revision | CSS Attribute Selectors & Buttons
- PBS 29 of x – JS Prototype Revision | Glyph Icons
- PBS 30 of x – Comparing JS Objects | Introducing WAI-ARIA
- PBS 31 of x – JS Static Functions | Checkboxes & Radio Buttons
- PBS 32 of x – JS Error Handling Revision | HTML Selects
- PBS 33 of x – JS Testing with QUnit
- PBS 34 of x – More JS Testing with QUnit
- PBS 35 of x – HTML Text Input | Introducing ‘Life’
- PBS 36 of x – More HTML Text Input | More Cellular Automata
- PBS 37 of x – JSDoc Demo
- PBS 38 of x – Taking Stock
- PBS 39 of x – HTML5 Form Validation
- PBS 40 of x – HTML5 Custom Validations with jQuery
- PBS 41 of x – Form Events
- PBS 42 of x – Playing the Game of Life
- PBS 43 of x – Introducing JavaScript ES6
- PBS 44 of x – ES6 Arguments & Objects
- PBS 45 of x – ES6 Arrays & Strings
- PBS 46 of x – ES6 Spread Operator, Arrow Functions & Classes
- PBS 47 of x – ES6 Polymorphism
- PBS 48 of x – A Closer Look at ‘this’ and ‘static’
- PBS 49 of x — Improving Our Cellular Automata
- PBS 50 of x — A Worked Example (Object Explorer)
- PBS 51 of x — Cellular Automata Wrap-up
- PBS 52 of X — Introducing Bootstrap 4
- PBS 53 of X — Bootstrap Utilities
- PBS 54 of X — More Bootstrap Utilities
- PBS 55 of X — Bootstrap Content
- PBS 56 of X — More Bootstrap Content
- PBS 57 of X — The Bootstrap Grid
- PBS 58 of X — Bootstrap Breakpoints
- PBS 59 of X — More Bootstrap Breakpoints
- PBS 60 of X — Bootstrap & jQuery
- PBS 61 of X — Bootstrap Jumbotrons & Badges
- PBS 62 of X — A Basic Bootstrap Form
- PBS 63 of X — Bootstrap Buttons
- PBS 64 of X — Bootstrap Form Layouts
- PBS 65 of X — Bootstrap Input Groups
- PBS 66 of X — Bootstrap Form Validation
- PBS 67 of X — Introducing Bootstrap Dropdowns
- PBS 68 of X — Bootstrap Navs
- PBS 69 of X — Bootstrap Navbars
- PBS 70 of X — Bootstrap Modals & Toasts
- PBS 71 of X — Bootstrap Spinners
- PBS 72 of X — HTML5 Templates
- PBS 73 of X — Mustache Templates
- PBS 74 of X — More Mustaches
- PBS 75 of X — AJAX Intro
- PBS 76 of X — AJAX with jQuery
- PBS 77 of X — More Callbacks & More AJAX
- PBS 78 of X — is.js & Bootstrap Popovers
- PBS 79 of X — Introducing Javascript Promises
- PBS 80 of X — JavaScript Promise Chains
- PBS 81 of X — The JavaScript Promise Utilities
- PBS 82 of X — Async & Await
- PBS 83 of X — Bootstrap Cards
- PBS 84 of X — Objects as Dictionaries in JavaScript (Redux & Update)
- PBS 85 of X — Objects as Arrays in JavaScript (Redux & Update)
- PBS 86 of X — JavaScript Function Objects (Redux & Update)
- PBS 87 of X — JavaScript Iterators Objects & Generator Functions
- PBS 88 of X — DOM & jQuery Objects Redux

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, and 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.

Listen Along: Chit Chat Accross the Pond Episode 434

## Our New Playground

Like 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, 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 try 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`

!

1 2 3 4 5 6 7 8 9 10 11 12 |
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 counter-intuitive:

1 2 3 4 5 6 7 8 |
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:

1 2 3 4 5 6 7 8 |
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.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
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 `||`

.

1 2 3 4 5 6 7 8 9 10 11 12 |
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.

1 |
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:

1 |
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:

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

1 2 3 4 |
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, and it will protect you from a whole class of subtle but very dangerous bugs creeping into you 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:

1 2 3 4 5 |
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:

1 2 3 4 5 6 7 8 |
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 more or less optional white space included. The canoncical K&R style is less cuddled than what I use (has more white space):

1 2 3 4 5 |
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:

1 2 3 4 5 6 7 8 |
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.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// 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 processes them.

[…] The entire tutorial is available here: bartbusschots.ie/…. […]