Expressions and Operators
Intro
- This tutorial covers Expressions and Operators.
- It is recommended that you follow along with each section below. Paste or type the code into your own JavaScript file and view the variable or expression values either with console.logs or using the VS Code Debug sidebar.
- The example code for the entire tutorial series is at github.com/LearnByCheating/javascript-tutorial. There is a separate file or folder for each tutorial, including the To-Do List example project. The Readme file has instructions on how to run the code.
1. Expressions
- An expression is any valid unit of code that resolves to a value. For example: 4 + 3 is an expression that resolves to 7.
- An expression can also have side effects such as assigning a value to a variable, like let x = 7.
- There are different types of expressions.
- Arithmetic expressions: Example:
4 + 3
resolves to 7. - String expressions: Example: Add the strings
"Hello" + " world!"
together. Resolves to "Hello world!" - Logical expressions: Resolve to true or false.
7 > 6
resolves to true. - Left hand expressions: Have an operator on the left, generally a keyword. Examples:
- The new operator instantiates a new object.
new String('Hello")
resolves to a string object "Hello". - The typeof operator gets the data type of a value.
typeof 7
resolves to 'number'. - Primary expressions: Even literal values like the number
7
, the string"hello"
, keywordstrue
andfalse
are expressions. They are called primary expressions. Primary expressions are already at the lowest level and can't be evaluated any further.
2. Operators
- Operator: In JavaScript, an operator is a special symbol or keyword used to perform operations on data. Operators are used in expressions. In the expression 4 + 3, the + sign is the operator.
- Operands: are the data that is used in the expression. In the expression
4 + 3
, 4 and 3 are the operands.
- Operators can have one, two, or three operands.
- Unary operators: have one operand. Keyword operators are an example of this. In the expression
typeof 7
, typeof is the operator and 7 is the operand. The expression returns the data type 'number'.
- Binary operators: have two operands separated by the operator. Like
4 + 3
. The + sign is the operator and has operands 4 and 3 are on either side of it.
- Ternary operators: have three operands. JavaScript only has one example of this, the ternary conditional statement.
- The ternary conditional statement is a shorthand if/else statement. It has 3 operands.
const score = 77;
const pass = (score >= 60) ? true : false;- The condition on the left
score >= 60
is the first operand. - Then the
?
serves as an operator. - If the condition is true, the statement resolves to the second operand.
- A colon
:
serves as a second operator. - If the condition is false, the statement resolves to the third operand.
- There are several types of JavaScript operators like assignment operators, comparison operators, arithmetic operators and more. We'll go through each of them next.
3. Assignment Operators
- The first type of operator we will cover is the assignment operator.
- The standard assignment operator is the = sign. It is used to assign a value to a variable. Like
let x = 4
.
- Compound assignment operators: JavaScript also has compound assignment operators that can be used as a shortcut syntax for adding, subtracting, multiplying, or dividing a variable with a value and assigning the result back to the same variable.
- Addition compound assignment operator:
res += x
is shorthand forres = res + x
.
- Subtraction compound assignment operator:
res -= x
is shorthand forres = res - x
.
- Multiplication compound assignment operator:
res*= x
shorthand forres = res * x
.
- Division compound assignment operator:
res /= x
is shorthand forres = res / x
.
Example:
Set res to 4,
let res = 4;Then use compound assignment operators to add 3, subtract 2, multiply by 4, and divide by 5.
res += 3; // Same as res = res + 3 res; // returns 7 res -= 2; // Same as res = res - 2 res; // returns 5 res *= 4; // Same as res = res * 4 res; // returns 20 res /= 5; // Same as res = res / 5 res; // returns 4
4. Arithmetic operators
- Arithmetic operators take one or two operands and return a single numeric value.
- They include plus/minus, multiplication/division, remainders, exponents, and some unary operators.
Precedence Hierarchy:
[6:21 Video Timestamp]- JavaScript evaluates arithmetic expressions from left to right. But if the expression has multiple operators, it uses a hierarchy, shown below in order of precedence with the highest on top.
1 | (x + y) | grouping |
2 | x++; x-- | postfix increment/decrement |
3 | -x; +x; ++x; --x | unary operators: negation/conversion, prefix increment/decrement |
4 | x ** y | exponent |
5 | x * y; x / y; x % y; | multiply/divide/remainder |
6 | x + y; x - y; | addition/subtraction |
- Starting at the bottom. Addition and subtraction has the lowest precedence. Then comes multiplication and division.
- Exponents have higher precedence than multiplication and division.
- Then increment/decrement unary operators have higher precedence than exponents.
- And at the top are expressions placed in parentheses. So use parentheses to override the precedence hierarchy below it.
Examples:
let res = 4 - 2 + 3; // returns 5
- The above expression includes two arithmetic operators, subtraction and addition. They have the same precedence to it just evaluates from left to right.
res = 4 * 2 + 3; // returns 11
- The above expression has a multiplication operator, then addition. Multiplication has higher precedence than addition. But it is already on the left side so it executes first anyway. The line executes in the order shown and resolves to 11.
res = 3 + 4 * 2; // returns 11
- Above we have an addition operator then a multiplication operator. Multiplication has higher precedence so 4 * 2 is done first, giving us 8. Then we add 3 giving us 11.
res = (3 + 4) * 2; // returns 14
- If you want to override the precedence in the expression, use parentheses. Parentheses have the highest precedence. Here we want to add 3 + 4 then multiply the result, 7, by 2. So 3 + 4 is put in parentheses. Multiplying that by 2 resolves the expression to 14.
Conversions:
- Now we will cover data type conversion.
- For arithmetic expressions (except string additions), non-number operands are converted to numbers using the Number() function before executing the expression.
- String digits: With the exception of addition, strings that are digits are converted to the number (e.g., '2' converts to 2).
res = 4 * '2'; // returns 8
res = 4 / '2'; // returns 2
res = 4 - '2'; // returns 2
- NaN: NaN is the numeric value for Not a Number. If either operand is NaN and the other is a number, the result will be NaN.
- Strings that are not numbers convert to NaN.
res = 4 + NaN; // NaN res = 4 * 'Some text'; // returns NaN
- Booleans: Boolean values are also converted to numbers. False is converted to 0. True is converted to 1.
res = 4 + false; // returns 4
res = 4 + true; // returns 5 res = '4' * true; // returns 4
- Addition conversions: If either of the operands is a string, then they are both treated as strings and concatenated.
res = 4 + '2'; // returns '42' res = 7 + 'Eleven'; // returns '7Eleven'
- In the first expression above, the number 4 gets converted to a string then concatenated to the string 2, resulting in the string '42'.
- In the second example, the number 7 is concatenated to the text string "Eleven" resulting in the string '7Eleven'.
Binary Arithmetic Operators:
- Binary arithmetic operators have two operands. These are the operators we most commonly think of. The plus
+
and minus-
signs, multiplication*
and division/
. The remainder operator which we'll cover next%
. And the exponent operator**
.
Examples:
res = 4 + 3; // 7
res = 4 - 3; // 1
res = 4 * 3; // 12
res = 4 / 3; // 1.333
// Remainder operator
res = 4 % 3; // 1
res = 4 ** 3; // 64
- The remainder operator uses the % character. It divides the left operand by the right operand and returns the remainder. In the above example, the remainder of 4 divided by 3 is 1.
- The next line is an example of the exponent operator, which uses two asterisk characters. The example takes 4 to the power of 3. So 4 times 4 times 4, which returns 64.
Unary Arithmetic Operators:
- Unary arithmetic operators have one operand. You'll see these most commonly in for loops.
- The increment operator is two plus signs
++
. If you have a variable you can increment it by 1 by adding the increment operator to it. If you put it before the variable it adds 1 to the variable before it is used.
let x = 7;
console.log(++x); // increments x by 1 then logs the value of x which is 8.
- If you place it after the variable it adds 1 to it after the variable is used.
let x = 7;
console.log(x++); // logs the value of x which is 7, then increments x by 1.
- Decrement works the same way only it uses minus minus
--
as the operator and subtracts 1 from the variable.
let x = 7;
console.log(--x); // decrements x by 1 then logs the value of x which is 6.
let x = 7;
console.log(x--); // logs the value of x which is 7, then decrements x by 1.
Unary plus/minus operator:
- A single plus or minus sign added before a variable converts it to a number if it is a string digit.
- It doesn't change the underlying variable value though. It just gives you a copy of it as a number.
let y = '7';
res = +y; res; // returns 7 y; // returns '7'. Y did not change.
- The minus sign will convert the string digit to a number and make it negative. But it doesn't change the underlying variable value. Z is still the string value '7'
let z = '7'; let res = -z; res; // returns -7 z; // returns '7'. Z did not change
5. Comparison operators
- Comparison operators compare two operands and return true or false. They can check for equality, inequality, greater than, greater than or equal to, less than, less than or equal to.
- When checking for equality, you can check for strict equality with 3 equal signs
===
, or loose equality with two==
.
- You can also check for strict inequality with
!==
or loose inequality with!=
.
Loose Equality and Inequality
- Loose equality, with two equal signs, will do data type conversions when doing the comparison. For example, if one value is a number data type, like the number 7, and the other is a string, like the digit character "7" in quotes, the string will be converted to a number for the comparison.
7 == '7'; // returns true
- In loose equality, when comparing Boolean values to numbers, true converts to 1, and false converts to 0.
1 == true; // returns true
0 == false; // returns true
- In loose equality, undefined and null are equal, in strict equality they are not.
undefined == null; // returns true
Strict equality and inequality
- Strict equality checks for equality of the value and data type.
- The strict equality operator is 3 equal signs
===
. - The strict inequality operator is
!==
. - Expressions are evaluated before doing the comparison.
- Examples:
7 === (5 + 2);
// returns true. The resolved expressions are both 7 and the data type for both is number.7 === (5 + 8);
// returns false. The resolved expressions are not equal.7 !== (5 + 8);
// returns true. !== checks if they are NOT equal. Since the resolved expressions are not equal, it returns true.7 === '7';
// returns false. The data types do not match. One is a number and the other is a string.true === 1;
// returns false.undefined === null;
// returns false.
Loose Equality and Inequality
- Loose equality uses
==
as the operator. Loose inequality uses!=
. Loose equality does some type conversions before doing the equality check. - When a number is compared to a digit string, the string converts to a number before doing the comparison.
7 == '7';
// returns true.- When a boolean is compared to the numbers 0 or 1, 0 converts to false and 1 converts to true.
true == 1;
// returns true.- Undefined and null are equal when using loose equality.
undefined == null;
// returns true.
Objects including arrays are compared by reference
- Objects are compared by whether they reference the same object in memory or not. When an object when created it is stored in heap memory. The variable it is assigned to holds the object's memory address. Two objects may happen to have identical properties but if they were created as separate objects then they are not equal.
- Example:
{ name: 'Joey' } === { name: 'Joey' }; // Returns false
- Arrays: Arrays are a type of object so the same principles hold true.
const arr = [1, 2, 3];
arr === [1, 2, 3]; // false, different arrays in memory.
const arrCopy = arr; // Assign variable to arr.
arr === arrCopy; // true, they both point to the same array in memory.
- The two arrays being compared in the example above have the same values, but they are not the same array. They are stored at different memory addresses.
- Next we declared another variable named arrCopy and set it to the arr variable. So now arr and arrCopy both hold the same memory address and therefore are equal.
Relational comparisons
- Relational comparisons are greater than
>
, greater than or equal>=
, less than<
, less than or equal<=.
- JavaScript does data type conversion for these compares.
7 > 6; // returns true 4 <= '9'; // returns true
6. Logical operators
You may need to evaluate two or more conditions together in an if statement. For that you can use the:
Logical OR (||): The OR operator in a conditional resolves to true if one or both of the conditions is true.
Logical NOT (!): Use the
- Logical AND (
&&
) operator. - or the logical OR (
||
) operator.
- Expressions with logical operators resolve to true or false.
Logical operators: Used in conditional statements
[17:26 Video Timestamp]Logical AND (&&): if there are two conditions, use the logical AND operator if both conditions need to be true.
if (true && true) { console.log('Both conditions are true'); }
- In the above simple example we used the primary expression true for both conditions. Since they are both true the condition passes.
const x = 7; if (typeof x === 'number' && x > 0) { console.log('x contains a positive number'); }
- In the above example we first check if variable x is a number. Checking the data type of a variable avoids throwing an error if x is not defined.
- If it is a number we check if the value is greater than 0. Since the value of x is the number 7, both expressions are true so the condition is true.
Logical OR (||): The OR operator in a conditional resolves to true if one or both of the conditions is true.
if (true || false) {
console.log('At least one of the conditions was true');
}
- In the above simple example one of the conditions is true so the if statement condition resolves to true.
const x = 7;
if (x < 1 || x > 10) {
console.log('x is not between 1 and 10');
}
- The above example checks if the value of x is less than 1 or greater than 10. If either of those expressions is true then the condition resolves to true. But since x is 7, neither is true so the condition is is false and doesn't execute the if statement.
Logical NOT (!): Use the
!
Not operator to switch the boolean from true to false or vice versa.let x = 7;
if (!x === undefined) {
console.log('x has a value');
}
- If a variables has not been initialized with a value, its value is undefined. The above condition checks that variable x is not undefined.
Logical operators: Short-circuit evaluation
- You can use AND or OR operators as a kind of shorthand conditional statement. This is frequently used in React applications.
- The values on either side of the logical operator are converted to boolean values using Boolean conversion rules:
- Falsy: Falsy values include false, null, 0, NaN, an empty string "", and undefined. Falsy values resolve to false.
- Truthy: All other values are considered truthy. That includes all numbers except 0, all strings except an empty string, all objects and arrays even if they have no properties or elements. Truthy values resolve to true.
- If you use the logical AND operator (
&&
) on two expressions, it returns the left operand if it is falsy ignoring the one on the right. If the left operand is truthy, it returns the right operand.
let res = 0 && 5; res; // returns 0
res = 1 && 6; res // returns 6
- Logical OR (
||
) returns the left operand if it is truthy, otherwise returns the right operand.
const val; let name = val || 'Not provided'; name; // returns 'Not provided'
- In the above example, the val variable was not initialized with a value so its value is undefined.
- Undefined is falsy so it converts to the boolean false.
- Using short-circuit evaluation with the OR operator, the left operand is false so the right operand value gets returned.
val = 'Joey' name = val || 'Not provided'; name; // returns 'Joey';
- The above is the opposite scenario. The val variable is set to the string value 'Joey'.
- Non-empty strings are truthy so it converts to the boolean true.
- Using short-circuit evaluation with the OR operator, the left operand is true so its value gets returned.
7. String operators
- Some of the above operators can be applied to strings. Comparison operators can be used to compare strings.
- To do greater than and less than comparisons, strings are compared by the first character. If they are equal then they are compared by the second character. And so on.
- The comparison is based on standard lexicographical ordering, using Unicode decimal values. Numbers 0-9 come first. Then upper case letters A-Z. Then lower case a-z.
'Hello world' !== 'hello world'; // returns true
- In the above equality comparison the two strings are not equal since one has a capital letter and the other does not.
'a' < 'z'; // returns true
- For relational comparisons a is less than z.
'Alex' < 'Brenda'; // returns true
- Alex is less than Brenda. These are compared by the first character. Capital B comes after capital A so its Unicode number is higher.
'a' > 'Z'; // returns true
- In the above comparison lower case a is greater than upper case Z. The capital letters A-Z as a group come before the lower case letters as a group. So all lower case letters are greater than all upper case letters.
'Hello' + ' world'; // returns "Hello world"
- The plus operator concatenates two strings together.
- The above statement adds the string "Hello" with the string " world". This returns the combined string "Hello world"
- Lastly, the compound assignment operator can be used to repeatedly add strings to the end of the same string variable. Below we are creating an HTML unordered list from a JavaScript array.
res = '<ul>';
const arr = ['Joey', 'Sheena', 'Johnny', 'Judy'];
arr.forEach((name) => {
res += `<li>${name}</li>`;
});
res += '</ul>';
- First we assign an opening unordered list tag to the res variable.
- Then we apply the forEach iterator to the arr array, and for each item we put the name in HTML list tags and add it to the res variable.
- After the array has been fully iterated through, we add a closing </ul> tag to the string and we are done.
- If this was used for a web page it would create an unordered list of all the names in array to display.
Conclusion
If you have the CheatSheet desktop app and downloaded the JavaScript CheatSheet, then go through the flashcards for this category to the point where you can answer them all in order and shuffled.