Operators (Arithmetic, Comparison, Logical)
Operators are symbols or keywords that perform operations on operands (values or variables). JavaScript provides various types of operators to manipulate data, make comparisons, and control program flow.
Arithmetic Operators
Arithmetic operators perform mathematical calculations on numbers.
Basic Arithmetic Operators
javascriptlet a = 10; let b = 3; // Addition (+) console.log(a + b); // 13 console.log(5 + 3); // 8 console.log("5" + 3); // "53" (string concatenation) // Subtraction (-) console.log(a - b); // 7 console.log(10 - 4); // 6 // Multiplication (*) console.log(a * b); // 30 console.log(4 * 5); // 20 // Division (/) console.log(a / b); // 3.333... console.log(15 / 3); // 5 console.log(10 / 0); // Infinity // Modulus/Remainder (%) console.log(a % b); // 1 (10 divided by 3 leaves remainder 1) console.log(17 % 5); // 2 console.log(10 % 2); // 0 (even number) // Exponentiation (**) - ES2016 console.log(a ** b); // 1000 (10 to the power of 3) console.log(2 ** 3); // 8 console.log(4 ** 0.5); // 2 (square root)
Unary Arithmetic Operators
javascriptlet x = 5; // Unary plus (+) - converts to number console.log(+x); // 5 console.log(+"10"); // 10 console.log(+true); // 1 console.log(+false); // 0 // Unary minus (-) - negates the value console.log(-x); // -5 console.log(-(-5)); // 5 // Increment (++) let counter = 0; console.log(++counter); // 1 (pre-increment: increment then return) console.log(counter++); // 1 (post-increment: return then increment) console.log(counter); // 2 // Decrement (--) let countdown = 5; console.log(--countdown); // 4 (pre-decrement) console.log(countdown--); // 4 (post-decrement) console.log(countdown); // 3
Practical Arithmetic Examples
javascript// Calculator functions function calculator(a, b, operation) { switch (operation) { case "+": return a + b; case "-": return a - b; case "*": return a * b; case "/": return b !== 0 ? a / b : "Cannot divide by zero"; case "%": return a % b; case "**": return a ** b; default: return "Invalid operation"; } } console.log(calculator(10, 3, "+")); // 13 console.log(calculator(10, 3, "/")); // 3.333... console.log(calculator(10, 0, "/")); // "Cannot divide by zero" // Common use cases let price = 99.99; let quantity = 3; let taxRate = 0.08; let subtotal = price * quantity; let tax = subtotal * taxRate; let total = subtotal + tax; console.log(`Subtotal: $${subtotal.toFixed(2)}`); console.log(`Tax: $${tax.toFixed(2)}`); console.log(`Total: $${total.toFixed(2)}`); // Check if number is even or odd function isEven(num) { return num % 2 === 0; } console.log(isEven(4)); // true console.log(isEven(7)); // false // Generate random number in range function randomBetween(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } console.log(randomBetween(1, 10)); // Random number between 1 and 10
Comparison Operators
Comparison operators compare two values and return a boolean result.
Equality Operators
javascriptlet a = 5; let b = "5"; let c = 5; // Strict equality (===) - checks value AND type console.log(a === c); // true (same value and type) console.log(a === b); // false (different types) console.log(5 === 5); // true console.log("hello" === "hello"); // true // Strict inequality (!==) console.log(a !== b); // true (different types) console.log(a !== c); // false (same value and type) // Loose equality (==) - performs type conversion console.log(a == b); // true (converts "5" to 5) console.log(a == c); // true console.log(0 == false); // true (false converts to 0) console.log("" == false); // true (both convert to 0) console.log(null == undefined); // true (special case) // Loose inequality (!=) console.log(a != b); // false (converts "5" to 5) console.log(5 != "6"); // true
Relational Operators
javascriptlet x = 10; let y = 5; let z = "10"; // Greater than (>) console.log(x > y); // true console.log(y > x); // false console.log(x > z); // false (10 > 10 after conversion) // Greater than or equal (>=) console.log(x >= y); // true console.log(x >= z); // true (10 >= 10 after conversion) console.log(y >= x); // false // Less than (<) console.log(y < x); // true console.log(x < y); // false // Less than or equal (<=) console.log(y <= x); // true console.log(x <= z); // true (10 <= 10 after conversion) console.log(x <= y); // false // String comparison (lexicographic) console.log("apple" < "banana"); // true console.log("Apple" < "apple"); // true (uppercase comes first) console.log("10" < "2"); // true (string comparison, not numeric) console.log("10" < "9"); // true (string comparison)
Comparison Best Practices
javascript// Always use strict equality unless you specifically need type conversion let userInput = "5"; let targetNumber = 5; // Poor - can lead to unexpected results if (userInput == targetNumber) { console.log("Match found"); } // Better - explicit and predictable if (Number(userInput) === targetNumber) { console.log("Match found"); } // Or convert both to same type if (String(targetNumber) === userInput) { console.log("Match found"); } // Comparing objects and arrays let arr1 = [1, 2, 3]; let arr2 = [1, 2, 3]; let arr3 = arr1; console.log(arr1 === arr2); // false (different objects) console.log(arr1 === arr3); // true (same reference) // To compare array contents function arraysEqual(a, b) { return JSON.stringify(a) === JSON.stringify(b); } console.log(arraysEqual(arr1, arr2)); // true // Null and undefined comparisons let value1 = null; let value2 = undefined; let value3 = 0; console.log(value1 == value2); // true (special case) console.log(value1 === value2); // false (different types) console.log(value1 == value3); // false console.log(value2 == value3); // false // Safe null/undefined checks function isNullOrUndefined(value) { return value == null; // Catches both null and undefined } function isNotNullOrUndefined(value) { return value != null; // Excludes both null and undefined }
Logical Operators
Logical operators are used to combine or modify boolean values.
Basic Logical Operators
javascriptlet a = true; let b = false; let x = 5; let y = 10; // Logical AND (&&) - returns true if both operands are true console.log(a && b); // false console.log(true && true); // true console.log(x > 0 && y > 0); // true console.log(x > 10 && y > 0); // false // Logical OR (||) - returns true if at least one operand is true console.log(a || b); // true console.log(false || false); // false console.log(x > 10 || y > 0); // true console.log(x > 10 || y < 0); // false // Logical NOT (!) - inverts the boolean value console.log(!a); // false console.log(!b); // true console.log(!(x > 0)); // false console.log(!!(x > 0)); // true (double negation converts to boolean)
Short-Circuit Evaluation
Logical operators use short-circuit evaluation, which can be very useful:
javascript// AND (&&) short-circuit let user = { name: "John", age: 30 }; // If user exists, then access user.name console.log(user && user.name); // "John" let nullUser = null; console.log(nullUser && nullUser.name); // null (doesn't throw error) // Practical usage function greetUser(user) { user && user.name && console.log(`Hello, ${user.name}!`); } greetUser({ name: "Alice" }); // "Hello, Alice!" greetUser(null); // No output, no error // OR (||) short-circuit for default values let userName = ""; let displayName = userName || "Guest"; console.log(displayName); // "Guest" let settings = null; let theme = settings && settings.theme || "light"; console.log(theme); // "light" // Function with default parameters using || function createUser(name, age, city) { return { name: name || "Anonymous", age: age || 0, city: city || "Unknown" }; } console.log(createUser("John")); // { name: "John", age: 0, city: "Unknown" }
Nullish Coalescing Operator (??) - ES2020
javascript// Nullish coalescing (??) - returns right side only if left is null or undefined let value1 = null; let value2 = undefined; let value3 = 0; let value4 = ""; let value5 = false; console.log(value1 ?? "default"); // "default" console.log(value2 ?? "default"); // "default" console.log(value3 ?? "default"); // 0 (not null/undefined) console.log(value4 ?? "default"); // "" (not null/undefined) console.log(value5 ?? "default"); // false (not null/undefined) // Difference between || and ?? let config = { timeout: 0, retries: null, debug: false }; // Using || (problematic with falsy values) console.log(config.timeout || 5000); // 5000 (0 is falsy) console.log(config.debug || true); // true (false is falsy) // Using ?? (only null/undefined trigger default) console.log(config.timeout ?? 5000); // 0 (0 is not null/undefined) console.log(config.retries ?? 3); // 3 (null triggers default) console.log(config.debug ?? true); // false (false is not null/undefined)
Logical Assignment Operators - ES2021
javascriptlet a = true; let b = false; let x = null; let y = "hello"; // Logical AND assignment (&&=) a &&= false; // a = a && false console.log(a); // false // Logical OR assignment (||=) b ||= true; // b = b || true console.log(b); // true // Nullish coalescing assignment (??=) x ??= "default"; // x = x ?? "default" console.log(x); // "default" y ??= "default"; // y = y ?? "default" console.log(y); // "hello" (not null/undefined) // Practical examples let userPreferences = { theme: null, language: "en", notifications: false }; // Set defaults only if null/undefined userPreferences.theme ??= "light"; userPreferences.language ??= "en"; userPreferences.notifications ??= true; console.log(userPreferences); // { theme: "light", language: "en", notifications: false }
Assignment Operators
Assignment operators assign values to variables.
Basic Assignment
javascriptlet x = 10; // Basic assignment let y = x; // Assign value of x to y let z = x + y; // Assign result of expression
Compound Assignment Operators
javascriptlet num = 10; // Addition assignment (+=) num += 5; // num = num + 5 console.log(num); // 15 // Subtraction assignment (-=) num -= 3; // num = num - 3 console.log(num); // 12 // Multiplication assignment (*=) num *= 2; // num = num * 2 console.log(num); // 24 // Division assignment (/=) num /= 4; // num = num / 4 console.log(num); // 6 // Modulus assignment (%=) num %= 4; // num = num % 4 console.log(num); // 2 // Exponentiation assignment (**=) num **= 3; // num = num ** 3 console.log(num); // 8 // String concatenation assignment let message = "Hello"; message += " World"; message += "!"; console.log(message); // "Hello World!" // Array manipulation let numbers = [1, 2, 3]; numbers[0] += 10; // numbers[0] = numbers[0] + 10 console.log(numbers); // [11, 2, 3]
Operator Precedence and Associativity
Understanding operator precedence helps you predict how expressions are evaluated:
javascript// Precedence examples console.log(2 + 3 * 4); // 14 (not 20) - multiplication first console.log((2 + 3) * 4); // 20 - parentheses override precedence console.log(10 - 5 - 2); // 3 (left-to-right: (10 - 5) - 2) console.log(2 ** 3 ** 2); // 512 (right-to-left: 2 ** (3 ** 2)) // Mixed operators let result = 5 + 3 * 2 > 10 && true; // Step by step: // 1. 3 * 2 = 6 // 2. 5 + 6 = 11 // 3. 11 > 10 = true // 4. true && true = true console.log(result); // true // Use parentheses for clarity let clearResult = ((5 + 3) * 2) > 10 && true; console.log(clearResult); // true // Common precedence order (highest to lowest): // 1. Parentheses () // 2. Exponentiation ** // 3. Unary +, -, !, ++, -- // 4. Multiplication *, Division /, Modulus % // 5. Addition +, Subtraction - // 6. Comparison <, >, <=, >= // 7. Equality ==, !=, ===, !== // 8. Logical AND && // 9. Logical OR || // 10. Assignment =, +=, -=, etc.
Practical Examples
1. Form Validation
javascriptfunction validateRegistration(userData) { let errors = []; // Name validation if (!userData.name || userData.name.trim().length < 2) { errors.push("Name must be at least 2 characters long"); } // Age validation if (!userData.age || userData.age < 13 || userData.age > 120) { errors.push("Age must be between 13 and 120"); } // Email validation (basic) if (!userData.email || !userData.email.includes("@") || userData.email.length < 5) { errors.push("Please provide a valid email address"); } // Password validation if (!userData.password || userData.password.length < 8) { errors.push("Password must be at least 8 characters long"); } // Terms acceptance if (!userData.acceptTerms) { errors.push("You must accept the terms and conditions"); } return { isValid: errors.length === 0, errors: errors }; } // Test the validation let user1 = { name: "John Doe", age: 25, email: "john@example.com", password: "securepass123", acceptTerms: true }; let user2 = { name: "A", age: 12, email: "invalid", password: "123", acceptTerms: false }; console.log(validateRegistration(user1)); // { isValid: true, errors: [] } console.log(validateRegistration(user2)); // { isValid: false, errors: [...] }
2. Shopping Cart Logic
javascriptfunction calculateCartTotal(items, discountCode, userType) { let subtotal = 0; let itemCount = 0; // Calculate subtotal for (let item of items) { if (item.quantity > 0 && item.price > 0) { subtotal += item.price * item.quantity; itemCount += item.quantity; } } // Apply quantity discount let quantityDiscount = 0; if (itemCount >= 10) { quantityDiscount = subtotal * 0.1; // 10% discount for 10+ items } else if (itemCount >= 5) { quantityDiscount = subtotal * 0.05; // 5% discount for 5+ items } // Apply discount code let codeDiscount = 0; if (discountCode === "SAVE20") { codeDiscount = subtotal * 0.2; } else if (discountCode === "SAVE10") { codeDiscount = subtotal * 0.1; } // Apply user type discount let userDiscount = 0; if (userType === "premium") { userDiscount = subtotal * 0.15; } else if (userType === "student") { userDiscount = subtotal * 0.1; } // Take the best discount (not cumulative) let bestDiscount = Math.max(quantityDiscount, codeDiscount, userDiscount); // Calculate tax let taxableAmount = subtotal - bestDiscount; let tax = taxableAmount * 0.08; // 8% tax // Calculate shipping let shipping = 0; if (subtotal < 100 && itemCount > 0) { shipping = 10; // $10 shipping for orders under $100 } let total = subtotal - bestDiscount + tax + shipping; return { subtotal: Number(subtotal.toFixed(2)), discount: Number(bestDiscount.toFixed(2)), tax: Number(tax.toFixed(2)), shipping: Number(shipping.toFixed(2)), total: Number(total.toFixed(2)), itemCount: itemCount }; } // Test the cart calculation let cartItems = [ { name: "Laptop", price: 999, quantity: 1 }, { name: "Mouse", price: 25, quantity: 2 }, { name: "Keyboard", price: 75, quantity: 1 } ]; console.log(calculateCartTotal(cartItems, "SAVE20", "premium"));
3. Game Score Calculator
javascriptfunction calculateGameScore(player) { let baseScore = 0; // Points for different achievements baseScore += player.kills * 10; baseScore += player.assists * 5; baseScore += player.objectives * 25; // Bonus multipliers let multiplier = 1; // Winning bonus if (player.won) { multiplier += 0.5; } // Performance bonuses if (player.kills > 20) { multiplier += 0.3; // Killing spree bonus } if (player.deaths === 0 && player.kills > 0) { multiplier += 0.5; // Flawless victory bonus } // Penalties if (player.deaths > player.kills * 2) { multiplier -= 0.2; // Poor performance penalty } // Ensure multiplier doesn't go below 0.5 multiplier = Math.max(multiplier, 0.5); let finalScore = Math.round(baseScore * multiplier); // Rank calculation let rank = "Bronze"; if (finalScore >= 1000) { rank = "Diamond"; } else if (finalScore >= 750) { rank = "Gold"; } else if (finalScore >= 500) { rank = "Silver"; } return { baseScore: baseScore, multiplier: Number(multiplier.toFixed(2)), finalScore: finalScore, rank: rank }; } // Test the score calculator let player1 = { kills: 15, deaths: 3, assists: 8, objectives: 2, won: true }; let player2 = { kills: 5, deaths: 15, assists: 2, objectives: 0, won: false }; console.log(calculateGameScore(player1)); // High score with bonuses console.log(calculateGameScore(player2)); // Lower score with penalties
Common Mistakes and Best Practices
1. Equality Comparison Mistakes
javascript// Mistake: Using == instead of === let userInput = "0"; if (userInput == false) { // true - unexpected! console.log("This runs unexpectedly"); } // Better: Use strict equality if (userInput === "false") { // false - expected console.log("This won't run"); } // Or explicit conversion if (Boolean(userInput) === false) { // false - userInput is truthy console.log("This won't run"); }
2. Logical Operator Misunderstanding
javascript// Mistake: Assuming && always returns boolean let user = { name: "John" }; let result = user && user.name; // Returns "John", not true console.log(typeof result); // "string" // If you need boolean let hasName = !!(user && user.name); // true console.log(typeof hasName); // "boolean" // Or use explicit check let hasNameExplicit = user !== null && user.name !== undefined;
3. Operator Precedence Confusion
javascript// Mistake: Unclear precedence let result = 5 + 3 * 2 > 10 && true || false; console.log(result); // What does this return? // Better: Use parentheses for clarity let clearResult = ((5 + (3 * 2)) > 10) && (true || false); console.log(clearResult); // Much clearer
Practice Exercises
javascript// Exercise 1: Build a comprehensive calculator function advancedCalculator(a, b, operation) { // Validate inputs if (typeof a !== "number" || typeof b !== "number") { return "Error: Both operands must be numbers"; } if (!isFinite(a) || !isFinite(b)) { return "Error: Operands must be finite numbers"; } switch (operation) { case "+": return a + b; case "-": return a - b; case "*": return a * b; case "/": return b !== 0 ? a / b : "Error: Division by zero"; case "%": return b !== 0 ? a % b : "Error: Division by zero"; case "**": return a ** b; case "avg": return (a + b) / 2; case "max": return Math.max(a, b); case "min": return Math.min(a, b); default: return "Error: Invalid operation"; } } // Test the calculator console.log(advancedCalculator(10, 3, "+")); // 13 console.log(advancedCalculator(10, 0, "/")); // "Error: Division by zero" console.log(advancedCalculator("10", 3, "+")); // "Error: Both operands must be numbers" // Exercise 2: Create a smart comparison function function smartCompare(a, b, operator) { // Handle null/undefined if (a == null || b == null) { if (operator === "===" || operator === "!==") { return operator === "===" ? a === b : a !== b; } return "Error: Cannot compare null/undefined values"; } // Convert to same type if both are numeric strings if (typeof a === "string" && typeof b === "string") { let numA = Number(a); let numB = Number(b); if (!isNaN(numA) && !isNaN(numB)) { a = numA; b = numB; } } switch (operator) { case "===": return a === b; case "!==": return a !== b; case ">": return a > b; case ">=": return a >= b; case "<": return a < b; case "<=": return a <= b; default: return "Error: Invalid operator"; } } // Test the comparison function console.log(smartCompare("10", "5", ">")); // true (converts to numbers) console.log(smartCompare("apple", "banana", "<")); // true (string comparison) console.log(smartCompare(null, undefined, "===")); // false // Exercise 3: Build a conditional logic evaluator function evaluateConditions(conditions, operator) { if (!Array.isArray(conditions) || conditions.length === 0) { return false; } switch (operator.toUpperCase()) { case "AND": return conditions.every(condition => Boolean(condition)); case "OR": return conditions.some(condition => Boolean(condition)); case "NAND": return !conditions.every(condition => Boolean(condition)); case "NOR": return !conditions.some(condition => Boolean(condition)); case "XOR": return conditions.filter(condition => Boolean(condition)).length === 1; default: return "Error: Invalid logical operator"; } } // Test the evaluator console.log(evaluateConditions([true, true, false], "AND")); // false console.log(evaluateConditions([true, true, false], "OR")); // true console.log(evaluateConditions([true, false], "XOR")); // true console.log(evaluateConditions([true, true], "XOR")); // false
What's Next?
Excellent! You now have a comprehensive understanding of JavaScript operators. In the next lesson, we'll explore Conditionals (if, switch) and learn how to make decisions in your code using the comparison and logical operators you just mastered.
Key Takeaways
- •Arithmetic operators perform mathematical calculations
- •Comparison operators compare values and return booleans
- •Logical operators combine or modify boolean values
- •Use strict equality (===) instead of loose equality (==) for predictable results
- •Short-circuit evaluation in logical operators can be used for conditional execution
- •Operator precedence determines evaluation order - use parentheses for clarity
- •Assignment operators provide shortcuts for common operations
- •Always validate inputs when performing operations
- •Understand the difference between || and ?? for default values
Operators are the building blocks for creating logic in your programs. Master them, and you'll be able to create complex conditions and calculations with confidence!