1.2 Lesson Examples: Logical operators and control flow
JavaScript supports a compact set of statements, specifically control flow statements, that you can use to incorporate a great deal of interactivity in your application.
Block Statements
Statements meant to be executed after a control flow operation will be grouped into what is called a block statement. These statements are wrapped into a pair of curly braces:
{
console.log("hello");
console.log("roar");
}
Block scope
We've seen that the scope in JavaScript changes often. In the case of block statements, there is no scope created.
var name = "james";
{
var name = "adriana";
}
console.log(x); // outputs gerry
Only functions introduce scope in Javascript.
Conditional statements
Conditional statements are a way of essentially skipping over a block of code if it does not pass a boolean expression. JavaScript supports two conditional statements: if
...else
and switch
.
if...else statement
if(expr) { code }
... means run the code
block if expr
is true
if (1 > 0) { console.log("hi") }
//=> hi
When you need to test more than one case, you may use else if
:
var name = "kittens";
if (name == "puppies") {
name += "!";
} else if (name == "kittens") {
name += "!!";
} else {
name = "!" + name;
}
name == "kittens!!"
//=> true
Note: It is recommended to not assign variables in the conditional expression, because the assignment of a value to a variable, like this:
student = "Jason";
//=> "Jason"
The expression above will return the value (as shown on the second line), so if you assign a truthy value inside a conditional statement, then this condition will always be true, or if you assign something undefined, it will make the conditional statement false (because undefined is falsy). Another potential issue with this is that it can be confused with equality(==
). The example below is the illustration of WHAT NOT TO DO, in general:
if (x = 3) {
console.log("boo");
}
Truthy & Falsy
All of the following become false when converted to a Boolean
false
0
""
(empty string)NaN
null
undefined
All other values become true when converted to a Boolean
Do not confuse the primitive boolean values true
and false
with the true and false values of the Boolean object. For example:
var b = new Boolean(false);
if (b) { console.log("true") }
//=> true
There is a simple way of verifying the thruthyness or falsiness of a value. When you add !
in front of a value, the returned value will be the inverse of the value in a boolean. So if you add two !
then you'll get the boolean value of the original one:
!!1
//=> true
!!0
//=> false
!!-1
//=> true
!![]
//=> true
!!{}
//=> true
!!null
//=> false
!!""
//=> false
Boolean/Logical Operators
Logical operators will always return a boolean value true
or false
.
There are two "binary" operators that require two values:
- AND, denoted
&&
- OR, denoted
||
A third "unary" operatory requires only one value:
- NOT, denoted
!
&& (AND)
The &&
operator requires both left and right values to be true
in order to return true
:
true && true
//=> true
Any other combination is false.
true && false
//=> false
false && false
//=> false
|| (OR)
The ||
operator requires just one of the left or right values to be true
in order to return true.
true || false
//=> true
false || true
//=> true
false || false
//=> false
Only false || false
will return false
The !
takes a value and returns the opposite boolean value, i.e.
!(true)
//=> false
The &&
and ||
operators use short-circuit logic, which means whether they will execute their second operand is dependent on the first. This is useful for checking for null objects before accessing their attributes:
var name = o && o.getName();
In this case, if the first operand o
is false, then the second operand o.getName()
will not be evaluated. The expression is basically saying "we already know the whole &&
expression is false, because o
is falsey. Why bother dealing with the second operand?"
Or for setting default values:
var name = otherName || o.getName();
In this case, if the first operand otherName
is false, then we'll see that "my name"
will be returned. If othername is truthy (e.g. it contains a value), it will get returned, and the second expression won't even be evaluated. The expression is basically saying "we already know the whole ||
expression is true, because o
is truthy. Why bother dealing with the second operand?"
Comparison Operators
Comparisons in JavaScript can be made using <
, >
, <=
and >=
. These work for both strings and numbers. This is both useful, and can be the source of frustration for some developers, since most languages do not implicitly convert strings to numbers the way that JavaScript does.
"A" > "a"
//=> false
"b" > "a"
//=> true
12 > "12"
//=> false
12 >= "12"
//=> true
Equality Operator ==
Equality is a bit more complex. There are 2 ways in JavaScript to verify equality.
When verifying equality using double equal ==
, JavaScript does a lot of the "type coercion" in the background. Like we mentioned above, if the operands have a different type (ie: the number 1
and the string "1"
), JavaScript will try to change the type of both operands to check whether they are equal. This means that a lot of times, expressions will return equal more easily than if we were stricter about what things were equivalent. Some examples:
"dog" == "dog";
//=> true
1 == true;
//=> true
Equality Operator ===
To avoid type coercion and measure equality more strictly, use the triple-equals operator. Because ===
more truly measures actual equality, we'll use this far more often when checking whether too things are, in fact, the same thing.
Note: "Sameness" and "equality" have various definitions and can be somewhat "fuzzy". They can also differ by programming language. Because you'll often be measuring whether two things are equal, you should investigate the way this works carefully.
Some examples:
1 === true;
//=> false
true === true;
//=> true
"hello" === "hello"
//=> true
However, there are some incidents when it does not do what we expect, for example when working with empty objects or arrays:
{} === {}
//=> Uncaught SyntaxError: Unexpected token ===
[] === []
//=> false
[1,7] === [1,7]
//=> false
Switch Statement
The switch statement can be used for multiple branches based on a number or string:
var food = "apple";
switch(food) {
case 'pear':
console.log("I like pears");
break;
case 'apple':
console.log("I like apples");
break;
default:
console.log("No favourite");
}
//=> I like apples
In this case the switch
statement compares food
to each of the cases (pear
and apple
), and evaluates the expressions beneath them if there is a match. It uses ===
to evaluate equality.
The default clause is optional.
Iteration
Iterating is a way of incrementally repeating a task.
for
You can iterate over an array with:
var a = [1, 2, 3, 4, 5];
for (var i = 0; i < a.length; i++) {
console.log(i);
}
This is slightly inefficient as you are looking up the length property once every loop. An improvement is to chain the var
assignment:
var a = [1, 2, 3, 4, 5];
for (var i = 0, len = a.length; i < len; i++) {
console.log(i);
}
Notice the placement of the comma and semi-colons.