Operators & Expressions in JavaScript
Operators are symbols that perform operations on operands (values and variables). Expressions are combinations of values, variables, and operators that evaluate to a value. Understanding operators and expressions is fundamental to writing effective JavaScript code.
Arithmetic Operators
Arithmetic operators perform mathematical operations on numeric values.
// Basic arithmetic operators
let a = 10;
let b = 3;
// Addition (+)
let sum = a + b; // 13
// Subtraction (-)
let difference = a - b; // 7
// Multiplication (*)
let product = a * b; // 30
// Division (/)
let quotient = a / b; // 3.3333...
// Modulus (%) - returns the division remainder
let remainder = a % b; // 1
// Exponentiation (**) - ES2016 (ES7)
let power = a ** b; // 10^3 = 1000
// Increment (++)
let c = 5;
c++; // Post-increment: returns c first, then adds 1
console.log(c); // 6
let d = 5;
++d; // Pre-increment: adds 1 first, then returns d
console.log(d); // 6
// Decrement (--)
let e = 5;
e--; // Post-decrement: returns e first, then subtracts 1
console.log(e); // 4
let f = 5;
--f; // Pre-decrement: subtracts 1 first, then returns f
console.log(f); // 4
Assignment Operators
Assignment operators assign values to JavaScript variables. They combine an arithmetic operation with assignment.
// Basic assignment (=)
let x = 10;
// Addition assignment (+=)
x += 5; // Equivalent to: x = x + 5; (x is now 15)
// Subtraction assignment (-=)
x -= 3; // Equivalent to: x = x - 3; (x is now 12)
// Multiplication assignment (*=)
x *= 2; // Equivalent to: x = x * 2; (x is now 24)
// Division assignment (/=)
x /= 4; // Equivalent to: x = x / 4; (x is now 6)
// Modulus assignment (%=)
x %= 4; // Equivalent to: x = x % 4; (x is now 2)
// Exponentiation assignment (**=)
x **= 3; // Equivalent to: x = x ** 3; (x is now 8)
// Bitwise assignment operators
let y = 5; // Binary: 101
y &= 3; // Binary: y = 5 & 3 = 101 & 011 = 001 (y is now 1)
y |= 6; // Binary: y = 1 | 6 = 001 | 110 = 111 (y is now 7)
y ^= 3; // Binary: y = 7 ^ 3 = 111 ^ 011 = 100 (y is now 4)
y <<= 1; // Binary: y = 4 << 1 = 100 << 1 = 1000 (y is now 8)
y >>= 2; // Binary: y = 8 >> 2 = 1000 >> 2 = 10 (y is now 2)
y >>>= 1; // Binary: y = 2 >>> 1 = 10 >>> 1 = 1 (y is now 1)
Comparison Operators
Comparison operators compare values and return a boolean result (true or false).
let a = 5;
let b = 10;
let c = "5";
// Equal to (==) - compares values, performs type conversion
console.log(a == c); // true (5 == "5" after type conversion)
// Strict equal to (===) - compares both value and type
console.log(a === c); // false (number !== string)
// Not equal to (!=) - compares values, performs type conversion
console.log(a != b); // true (5 != 10)
// Strict not equal to (!==) - compares both value and type
console.log(a !== c); // true (number !== string)
// Greater than (>)
console.log(b > a); // true (10 > 5)
// Less than (<)
console.log(a < b); // true (5 < 10)
// Greater than or equal to (>=)
console.log(a >= 5); // true (5 >= 5)
// Less than or equal to (<=)
console.log(b <= 5); // false (10 <= 5)
// Ternary operator (condition ? expr1 : expr2)
let age = 20;
let status = age >= 18 ? "Adult" : "Minor";
console.log(status); // "Adult"
Logical Operators
Logical operators perform logical operations and return a boolean result.
let x = true;
let y = false;
// Logical AND (&&) - returns true if both operands are true
console.log(x && y); // false
// Logical OR (||) - returns true if at least one operand is true
console.log(x || y); // true
// Logical NOT (!) - reverses the boolean value
console.log(!x); // false
// Short-circuit evaluation
// With &&, if the first operand is false, the second is not evaluated
let a = false && someUndefinedFunction(); // someUndefinedFunction() is never called
// With ||, if the first operand is true, the second is not evaluated
let b = true || someUndefinedFunction(); // someUndefinedFunction() is never called
// Nullish coalescing operator (??) - ES2020
// Returns the right-hand operand when the left is null or undefined
let name = null;
let username = name ?? "Guest";
console.log(username); // "Guest"
// Optional chaining operator (?.) - ES2020
// Allows reading properties from nested objects without checking if each reference is valid
let user = {};
let city = user?.address?.city;
console.log(city); // undefined (no error thrown)
Bitwise Operators
Bitwise operators perform operations on binary representations of numbers.
let a = 5; // Binary: 101
let b = 3; // Binary: 011
// Bitwise AND (&)
console.log(a & b); // 1 (Binary: 101 & 011 = 001)
// Bitwise OR (|)
console.log(a | b); // 7 (Binary: 101 | 011 = 111)
// Bitwise XOR (^)
console.log(a ^ b); // 6 (Binary: 101 ^ 011 = 110)
// Bitwise NOT (~)
console.log(~a); // -6 (Binary: ~00000000000000000000000000000101 = 11111111111111111111111111111010)
// Left shift (<<)
console.log(a << 1); // 10 (Binary: 101 << 1 = 1010)
// Right shift (>>)
console.log(a >> 1); // 2 (Binary: 101 >> 1 = 10)
// Zero-fill right shift (>>>)
console.log(-5 >>> 1); // 2147483645 (Shifts and fills with zeros from the left)
String Operators
JavaScript also provides operators for working with strings.
// Concatenation operator (+)
let firstName = "John";
let lastName = "Doe";
let fullName = firstName + " " + lastName; // "John Doe"
// Concatenation assignment operator (+=)
let greeting = "Hello, ";
greeting += fullName; // "Hello, John Doe"
// Template literals (ES6+)
let message = `${greeting}! Welcome to our website.`;
console.log(message); // "Hello, John Doe! Welcome to our website."
// String comparison
console.log("apple" < "banana"); // true (lexicographical comparison)
console.log("10" > "2"); // false (string comparison, not numeric)
Special Operators
JavaScript has several special operators for specific purposes.
// typeof operator - returns the type of a variable or expression
console.log(typeof 42); // "number"
console.log(typeof "hello"); // "string"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object" (this is a known JavaScript quirk)
console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(typeof function(){}); // "function"
// instanceof operator - tests if an object is an instance of a specific class/constructor
let arr = [1, 2, 3];
console.log(arr instanceof Array); // true
console.log(arr instanceof Object); // true (arrays inherit from Object)
console.log(arr instanceof String); // false
// delete operator - deletes an object's property or an array element
let person = { name: "John", age: 30 };
delete person.age;
console.log(person); // { name: "John" }
// void operator - evaluates an expression and returns undefined
console.log(void 0); // undefined
console.log(void(2 + 3)); // undefined
// comma operator (,) - evaluates multiple expressions and returns the last one
let x = (1, 2, 3, 4, 5);
console.log(x); // 5
// The in operator - checks if a property exists in an object
console.log("name" in person); // true
console.log("age" in person); // false (we deleted it)
Operator Precedence
Operator precedence determines the order in which operators are evaluated in an expression.
// Precedence example
let result = 2 + 3 * 4; // 14, not 20 (multiplication has higher precedence)
// Using parentheses to control precedence
let result2 = (2 + 3) * 4; // 20
// Complex example
let x = 5;
let y = 10;
let z = 15;
let complex = x + y * z / 2 - 3; // 5 + (10 * 15) / 2 - 3 = 5 + 150 / 2 - 3 = 5 + 75 - 3 = 77
// Precedence order (from highest to lowest, simplified):
// 1. Grouping: ()
// 2. Member access: . []
// 3. Function call: ()
// 4. Postfix increment/decrement: x++ x--
// 5. Prefix increment/decrement, unary operators: ++x --x +x -x ~ ! typeof void delete
// 6. Exponentiation: **
// 7. Multiplication, division, modulus: * / %
// 8. Addition, subtraction: + -
// 9. Bitwise shift: << >> >>>
// 10. Relational: < <= > >= instanceof in
// 11. Equality: == != === !==
// 12. Bitwise AND: &
// 13. Bitwise XOR: ^
// 14. Bitwise OR: |
// 15. Logical AND: &&
// 16. Logical OR: ||
// 17. Nullish coalescing: ??
// 18. Conditional (ternary): ? :
// 19. Assignment: = += -= *= etc.
// 20. Comma: ,
Expressions in JavaScript
An expression is any valid unit of code that resolves to a value. There are several types of expressions in JavaScript.
// 1. Arithmetic expressions
let sum = 10 + 5; // 15
// 2. String expressions
let greeting = "Hello" + " " + "World"; // "Hello World"
// 3. Logical expressions
let isAdult = age >= 18; // true or false
// 4. Primary expressions
// - Literals
42; // Number literal
"hello"; // String literal
true; // Boolean literal
null; // null literal
/pattern/; // Regular expression literal
[1, 2, 3]; // Array literal
{a: 1, b: 2}; // Object literal
// - this keyword
function demo() {
console.log(this); // refers to the current object
}
// 5. Left-hand-side expressions
// - Property accessors
let person = { name: "John" };
person.name; // dot notation
person["name"]; // bracket notation
// - new operator
let date = new Date();
// - function call
Math.max(1, 2, 3);
// 6. Assignment expressions
let x = 5;
// 7. Conditional expressions
let status = age >= 18 ? "Adult" : "Minor";
// 8. Function expressions
let greet = function(name) {
return `Hello, ${name}!`;
};
// 9. Arrow function expressions (ES6+)
let multiply = (a, b) => a * b;
// 10. Destructuring assignment (ES6+)
let [first, second] = [1, 2];
let { name, age } = { name: "John", age: 30 };
Best Practices for Operators & Expressions
- Use
===
and!==
instead of==
and!=
to avoid unexpected type conversions - Use parentheses to make complex expressions more readable and to ensure correct precedence
- Be careful with increment/decrement operators in expressions (prefer separate statements)
- Avoid using the comma operator except in for loops
- Use template literals for string concatenation when possible
- Be aware of short-circuit evaluation with
&&
and||
- Use the nullish coalescing operator (
??
) instead of||
when you want to distinguish betweennull
/undefined
and falsy values
Common Pitfalls and Gotchas
There are several common mistakes and unexpected behaviors when working with JavaScript operators.
// 1. Type coercion with equality operators
console.log(0 == false); // true
console.log(0 === false); // false
console.log('' == false); // true
console.log('' === false); // false
// 2. Addition vs. concatenation
console.log(1 + 2); // 3 (addition)
console.log('1' + 2); // '12' (concatenation)
console.log(1 + '2'); // '12' (concatenation)
console.log(1 + 2 + '3'); // '33' (addition then concatenation)
console.log('1' + 2 + 3); // '123' (concatenation)
// 3. Increment/decrement in expressions
let x = 5;
let y = x++; // y = 5, x = 6
let a = 5;
let b = ++a; // b = 6, a = 6
// 4. Floating-point precision issues
console.log(0.1 + 0.2); // 0.30000000000000004, not exactly 0.3
console.log(0.1 + 0.2 === 0.3); // false
// 5. Logical operators with non-boolean values
console.log('hello' && 'world'); // 'world' (returns the last truthy value)
console.log('' || 'default'); // 'default' (returns the first truthy value)
console.log(null ?? 'default'); // 'default' (nullish coalescing)
console.log('' ?? 'default'); // '' (empty string is not nullish)
// 6. Automatic semicolon insertion
function returnObject() {
return // semicolon automatically inserted here!
{
value: 42
}
} // returns undefined, not the object
// 7. NaN behavior
console.log(NaN === NaN); // false
console.log(Number.isNaN(NaN)); // true (correct way to check)
// 8. Unary plus for type conversion
console.log(+'42'); // 42 (converts string to number)
console.log(+true); // 1
console.log(+false); // 0
console.log(+null); // 0
console.log(+undefined); // NaN
Practice Exercise
Create a JavaScript file that demonstrates the use of different operators. Try to solve these challenges:
- Write a function that calculates the area and perimeter of a rectangle using arithmetic operators
- Create a function that converts temperatures between Celsius and Fahrenheit
- Write a function that checks if a year is a leap year using logical operators
- Create a function that determines the grade (A, B, C, D, or F) based on a numeric score using the ternary operator
- Write a function that swaps two variables without using a temporary variable
Advanced Topic: Operator Overloading
Unlike some other programming languages, JavaScript does not support operator overloading directly. However, there are some workarounds:
- For objects, you can implement methods like
valueOf()
andtoString()
to control how objects behave with operators - The
+
operator can work with strings (concatenation) or numbers (addition) depending on the operand types - The
[Symbol.toPrimitive]
method (ES6+) gives more control over type conversion in different contexts
Example:
class Vector {
constructor(x, y) {
this.x = x;
this.y = y;
}
// Used for addition with +
valueOf() {
return Math.sqrt(this.x * this.x + this.y * this.y);
}
// Used for string concatenation
toString() {
return `(${this.x}, ${this.y})`;
}
// More control over conversion
[Symbol.toPrimitive](hint) {
if (hint === 'number') {
return this.valueOf();
}
if (hint === 'string') {
return this.toString();
}
return this.valueOf();
}
}