Primitive Data Types, Arrays, Loops, and Conditions - Part 2 [con't]
Booleans
There are only two values that belong to the boolean data type: the values true
and false
, used without quotes.
If you quote true
or false
, they become strings.
Logical Operators
There are three operators, called logical operators, that work with boolean values. These are:
!
—logical NOT (negation)&&
—logical AND||
—logical OR
!
operator.
If you use the logical NOT twice, you get the original value:
If you use a logical operator on a non-boolean value, the value is converted to boolean behind the scenes.
one
" was converted to a boolean true
and then negated. The result of negating true
is false
. In the next example, we negate twice so the result is true
.
Using double negation is an easy way to convert any value to its boolean equivalent. This is rarely useful, but on the other hand understanding how any value converts to a boolean is important. Most values convert to true
with the exception of the following (which convert to false
):
- The empty string
""
null
undefined
- The number 0
- The number
NaN
- The boolean
false
These six values are sometimes referred to as being falsy, while all others are truthy (including, for example, the strings "0", " ", and "false").
Let's see some examples of the other two operators—the logical AND and the logical OR. When you use AND, the result is true
only if all of the operands are true
. When using OR, the result is true
if at least one of the operands is true
.
Here's a table that lists the possible operations and their results (see example).
You can use several logical operations one after the other:
You can also mix && and || in the same expression. In this case, you should use parentheses to clarify how you intend the operation to work. Consider these:
Operator Precedence
You might wonder why the expression above (false && false || true && true
) returned true
. The answer lies in operator precedence. As you know from mathematics:
This is because multiplication has precedence over addition, so 2 * 3
is evaluated first, as if you've typed:
Similarly for logical operations, !
has the highest precedence and is executed first, assuming there are no parentheses that demand otherwise. Then, in the order of precedence, comes &&
and finally ||
. In other words:
is the same as:
Best Practice: Use parentheses instead of relying on operator precedence. This makes your code easier to read and understand.
Lazy Evaluation
If you have several logical operations one after the other, but the result becomes clear at some point before the end, the final operations will not be performed, because they can't affect the end result. Consider this:
Since these are all OR operations and have the same precedence, the result will be true
if at least one of the operands is true
. After the first operand is evaluated, it becomes clear that the result will be true
, no matter what values follow. So the JavaScript engine decides to be lazy (ok, efficient) and not do unnecessary work by evaluating code that doesn't affect the end result. You can verify this behavior by experimenting in the console:
This example also shows another interesting behavior—if JavaScript encounters a non-boolean expression as an operand in a logical operation, the non-boolean is returned as a result.
This behavior is something to watch out for and avoid, because it makes the code harder to understand. Sometimes you might see this behavior being used to define variables when you're not sure whether they were previously defined. In the next example, if the variable v is defined, its value is kept; otherwise, it's initialized with the value 10
.
This is simple and looks elegant, but be aware that it is not completely bulletproof. If mynumber
is defined and initialized to 0 (or to any of the six falsy values), this code might not behave in exactly the way it was designed to work.
Comparison
There's another set of operators that all return a boolean value as a result of the operation. These are the comparison operators. The following table lists them, together with some examples.
Operator symbol | Description | Example |
---|---|---|
== |
Equality comparison: Returns true when both operands are equal. The operands are converted to the same type before being compared. | >>> 1 == 1 true >>> 1 == 2 false >>> 1 == '1' true |
=== |
Equality and type comparison: Returns true if both operands are equal and of the same type. It's generally better and safer if you compare this way, because there's no behind-the-scenes type conversions. | >>> 1 === '1' false >>> 1 === 1 true |
!= |
Non-equality comparison: Returns true if the operands are not equal to each other (after a type conversion) | >>> 1 != 1 false >>> 1 != '1' false >>> 1 != '2' true |
!== |
Non-equality comparison without type conversion: Returns true if the operands are not equal OR they are different types. | >>> 1 !== 1 false >>> 1 !== '1' true |
> |
Returns true if the left operand is greater than the right one. | >>> 1 > 1 false >>> 33 > 22 true |
>= |
Returns true if the left operand is greater than or equal to the right one. | >>> 1 >= 1 true |
< |
Returns true if the left operand is less than the right one. | >>> 1 < 1 false >>> 1 < 2 true |
<= |
Returns true if the left operand is less than or equal to the right one. | >>> 1
true >>> 1 true |
An interesting thing to note is that NaN
is not equal to anything, not even itself.
Undefined and null
You get the undefined
value when you try to use a variable that doesn't exist, or one that hasn't yet been assigned a value. When you declare a variable without initializing it, JavaScript automatically initializes it to the value undefined
.
If you try using a non-existing variable, you'll get an error message.
If you use the typeof
operator on a non-existing variable, you get the string "undefined".
If you declare a variable without giving it a value, you won't get an error when you use that variable. But the typeof
still returns "undefined".
The null
value, on the other hand, is not assigned by JavaScript behind the scenes; it can only be assigned by your code.
Although the difference between null
and undefined
is small, it may be important at times. For example, if you attempt an arithmetic operation, you can get different results:
This is because of the different ways null
and undefined
are converted to the other primitive types. Below are examples that show the possible conversions.
Conversion to a number:
Conversion to a boolean:
Conversion to a string:
Primitive Data Types Recap
Let's quickly summarize what has been discussed so far:- There are five primitive data types in JavaScript:
- number
- string
- boolean
- undefined
- null
- Everything that is not a primitive is an object
- The number data type can store positive and negative integers or floats, hexadecimal numbers, octal numbers, exponents, and the special numbers
NaN
,Infinity
, and-Infinity
- The string data type contains characters in quotes
- The only values of the boolean data type are
true
andfalse
- The only value of the null data type is the value
null
- The only value of the undefined data type is the value
undefined
- All values become
true
when converted to a boolean, with the exception of the six falsy values:null
undefined
0
NaN
false