A Complete Guide to Programming Operators
Table of Contents
- Introduction to Operators
- Arithmetic Operators
- Assignment Operators
- Comparison Operators
- Logical Operators
- Bitwise Operators
- String Operators
- Type Operators
- Ternary/Conditional Operator
- Operator Precedence
- Operator Overloading
- Special Operators
- Short-Circuit Evaluation
- Common Pitfalls
- Interview Questions
Introduction to Operators
Operators are special symbols or keywords that perform operations on operands (values or variables). They are the building blocks of expressions and allow us to manipulate data, make decisions, and control program flow.
What Are Operators?
An operator is a symbol that tells the compiler or interpreter to perform a specific mathematical, logical, or relational operation.
// Basic operator examples let sum = 5 + 3; // '+' is an arithmetic operator let isEqual = (10 == 10); // '==' is a comparison operator let result = (age > 18) && (hasLicense); // '&&' is a logical operator
Types of Operators by Operand Count
| Type | Description | Examples |
|---|---|---|
| Unary | Operates on one operand | -5, !true, ++x |
| Binary | Operates on two operands | a + b, x && y |
| Ternary | Operates on three operands | condition ? a : b |
Arithmetic Operators
Arithmetic operators perform mathematical calculations on numeric values.
Basic Arithmetic Operators
# Python a = 10 b = 3 print(a + b) # Addition: 13 print(a - b) # Subtraction: 7 print(a * b) # Multiplication: 30 print(a / b) # Division: 3.333... print(a // b) # Floor division: 3 print(a % b) # Modulus (remainder): 1 print(a ** b) # Exponentiation: 1000
// JavaScript let a = 10; let b = 3; console.log(a + b); // 13 console.log(a - b); // 7 console.log(a * b); // 30 console.log(a / b); // 3.333... console.log(a % b); // 1 console.log(a ** b); // 1000 (ES7+)
// Java int a = 10; int b = 3; System.out.println(a + b); // 13 System.out.println(a - b); // 7 System.out.println(a * b); // 30 System.out.println(a / b); // 3 (integer division) System.out.println(a % b); // 1
Increment and Decrement Operators
// JavaScript let x = 5; // Post-increment: returns value, then increments console.log(x++); // 5 console.log(x); // 6 // Pre-increment: increments, then returns value console.log(++x); // 7 console.log(x); // 7 // Post-decrement console.log(x--); // 7 console.log(x); // 6 // Pre-decrement console.log(--x); // 5
# Python (no ++/-- operators) x = 5 x += 1 # Instead of x++ x -= 1 # Instead of x--
Unary Plus and Minus
// JavaScript let num = "42"; let negative = -10; console.log(+num); // 42 (converts to number) console.log(-negative); // 10 (negation) console.log(-num); // -42
Assignment Operators
Assignment operators assign values to variables.
Basic Assignment
// JavaScript let x = 10; // Basic assignment
Compound Assignment Operators
# Python x = 10 x += 5 # x = x + 5 (15) x -= 3 # x = x - 3 (12) x *= 2 # x = x * 2 (24) x /= 4 # x = x / 4 (6.0) x //= 2 # x = x // 2 (3) x %= 2 # x = x % 2 (1) x **= 3 # x = x ** 3 (1)
// JavaScript let x = 10; x += 5; // 15 x -= 3; // 12 x *= 2; // 24 x /= 4; // 6 x %= 2; // 0 x **= 3; // 0 // Bitwise compound assignment x = 5; x &= 3; // 1 (101 & 011 = 001) x |= 2; // 3 (001 | 010 = 011) x ^= 1; // 2 (011 ^ 001 = 010) x <<= 1; // 4 (010 << 1 = 100) x >>= 1; // 2 (100 >> 1 = 010)
Destructuring Assignment
// JavaScript - Array destructuring
let [a, b, c] = [1, 2, 3];
console.log(a, b, c); // 1, 2, 3
// Swapping variables
[a, b] = [b, a];
console.log(a, b); // 2, 1
// Object destructuring
let { name, age } = { name: "Alice", age: 30 };
console.log(name, age); // Alice, 30
# Python - Tuple unpacking a, b, c = 1, 2, 3 print(a, b, c) # 1, 2, 3 # Swapping a, b = b, a print(a, b) # 2, 1
Comparison Operators
Comparison operators compare two values and return a Boolean (true/false).
Equality Operators
// JavaScript - careful with equality! let x = 5; let y = "5"; console.log(x == y); // true (loose equality, type conversion) console.log(x === y); // false (strict equality, no type conversion) console.log(x != y); // false (loose inequality) console.log(x !== y); // true (strict inequality)
# Python x = 5 y = "5" print(x == y) # False (no type coercion) print(x != y) # True
Relational Operators
// JavaScript let a = 10; let b = 20; console.log(a > b); // false console.log(a >= b); // false console.log(a < b); // true console.log(a <= b); // true
Object Comparison
// JavaScript - objects compared by reference
let obj1 = { name: "Alice" };
let obj2 = { name: "Alice" };
let obj3 = obj1;
console.log(obj1 == obj2); // false (different references)
console.log(obj1 === obj2); // false
console.log(obj1 == obj3); // true (same reference)
// Deep comparison would require custom logic
function deepEqual(obj1, obj2) {
return JSON.stringify(obj1) === JSON.stringify(obj2);
}
Logical Operators
Logical operators combine Boolean values or expressions.
AND, OR, NOT
// JavaScript let isLoggedIn = true; let isAdmin = false; // AND (&&) - both must be true console.log(isLoggedIn && isAdmin); // false // OR (||) - at least one must be true console.log(isLoggedIn || isAdmin); // true // NOT (!) - inverts the value console.log(!isLoggedIn); // false console.log(!isAdmin); // true
# Python is_logged_in = True is_admin = False # AND print(is_logged_in and is_admin) # False # OR print(is_logged_in or is_admin) # True # NOT print(not is_logged_in) # False print(not is_admin) # True
Logical Operators with Non-Booleans
// JavaScript - short-circuit evaluation console.log(0 && 5); // 0 (falsy) console.log(5 && 10); // 10 (truthy) console.log(0 || 5); // 5 (truthy) console.log(5 || 10); // 5 (truthy) // Common patterns let name = userInput || "Guest"; // Default value let isValid = condition && doSomething(); // Conditional execution
# Python print(0 and 5) # 0 print(5 and 10) # 10 print(0 or 5) # 5 print(5 or 10) # 5 # Common patterns name = user_input or "Guest" # Default value
Nullish Coalescing Operator
// JavaScript - ?? operator (ES2020) let value = null ?? "default"; // "default" let value2 = 0 ?? "default"; // 0 (not null/undefined) let value3 = undefined ?? "default"; // "default" // vs OR operator let orValue = 0 || "default"; // "default" (0 is falsy)
Bitwise Operators
Bitwise operators perform operations on the binary representations of numbers.
Bitwise Operators Table
| Operator | Name | Example | Result |
|---|---|---|---|
& | AND | 5 & 3 | 1 (101 & 011 = 001) |
| | OR | 5 | 3 | 7 (101 | 011 = 111) |
^ | XOR | 5 ^ 3 | 6 (101 ^ 011 = 110) |
~ | NOT | ~5 | -6 (inverts bits) |
<< | Left shift | 5 << 1 | 10 (1010) |
>> | Right shift | 5 >> 1 | 2 (10) |
>>> | Zero-fill right shift | -5 >>> 1 | 2147483645 (JS only) |
Bitwise AND, OR, XOR
// JavaScript let a = 5; // Binary: 0101 let b = 3; // Binary: 0011 console.log(a & b); // 1 (0001) console.log(a | b); // 7 (0111) console.log(a ^ b); // 6 (0110)
Bitwise NOT
// JavaScript let x = 5; // Binary: 0101 console.log(~x); // -6 (11111111111111111111111111111010) // For 32-bit signed integers console.log(~x & 0xFFFFFFFF); // 4294967290 (unsigned)
Bitwise Shifts
// JavaScript let x = 5; // 0101 console.log(x << 1); // 10 (1010) (multiply by 2) console.log(x << 2); // 20 (10100) (multiply by 4) console.log(x >> 1); // 2 (10) (divide by 2) console.log(x >> 2); // 1 (1) (divide by 4) // Negative numbers let y = -5; console.log(y >> 1); // -3 (arithmetic shift preserves sign)
Bitwise Flags Example
// Using bitwise operators for flags
const PERMISSIONS = {
READ: 1 << 0, // 1 (001)
WRITE: 1 << 1, // 2 (010)
DELETE: 1 << 2, // 4 (100)
ADMIN: 1 << 3 // 8 (1000)
};
let userPermissions = PERMISSIONS.READ | PERMISSIONS.WRITE; // 3 (011)
// Check permission
function hasPermission(permissions, permission) {
return (permissions & permission) === permission;
}
console.log(hasPermission(userPermissions, PERMISSIONS.READ)); // true
console.log(hasPermission(userPermissions, PERMISSIONS.DELETE)); // false
// Add permission
userPermissions |= PERMISSIONS.DELETE; // Now has DELETE (7)
// Remove permission
userPermissions &= ~PERMISSIONS.WRITE; // Remove WRITE (5)
// Toggle permission
userPermissions ^= PERMISSIONS.READ; // Toggle READ
String Operators
Concatenation
// JavaScript
let firstName = "John";
let lastName = "Doe";
// + operator for concatenation
let fullName = firstName + " " + lastName;
console.log(fullName); // "John Doe"
// Template literals (ES6)
let greeting = `Hello, ${firstName} ${lastName}!`;
console.log(greeting); // "Hello, John Doe!"
# Python
first_name = "John"
last_name = "Doe"
# + operator
full_name = first_name + " " + last_name
print(full_name) # "John Doe"
# f-strings (Python 3.6+)
greeting = f"Hello, {first_name} {last_name}!"
print(greeting) # "Hello, John Doe!"
# format() method
greeting2 = "Hello, {} {}!".format(first_name, last_name)
String Comparison
# Python - lexicographic comparison
print("apple" < "banana") # True
print("Apple" < "apple") # True (ASCII comparison)
print("abc" == "abc") # True
# Case-insensitive comparison
print("APPLE".lower() == "apple".lower()) # True
// JavaScript
console.log("apple" < "banana"); // true
console.log("Apple" < "apple"); // true
console.log("abc" === "abc"); // true
// Locale-aware comparison
console.log("apple".localeCompare("banana")); // -1
Type Operators
typeof Operator
// JavaScript
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" (quirk)
console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(typeof function(){}); // "function"
// Checking array type
console.log(Array.isArray([])); // true
# Python
print(type(42)) # <class 'int'>
print(type("Hello")) # <class 'str'>
print(type(True)) # <class 'bool'>
print(type(None)) # <class 'NoneType'>
print(type([])) # <class 'list'>
print(type({})) # <class 'dict'>
print(type(lambda x: x)) # <class 'function'>
# isinstance() - better for type checking
print(isinstance(42, int)) # True
print(isinstance([], list)) # True
print(isinstance("abc", str)) # True
instanceof Operator
// JavaScript
class Animal {}
class Dog extends Animal {}
let dog = new Dog();
console.log(dog instanceof Dog); // true
console.log(dog instanceof Animal); // true
console.log(dog instanceof Object); // true
// Primitive types
console.log(42 instanceof Number); // false (primitive)
console.log(new Number(42) instanceof Number); // true
in Operator
// JavaScript
let person = { name: "Alice", age: 30 };
console.log("name" in person); // true
console.log("salary" in person); // false
console.log("toString" in person); // true (inherited)
// Arrays
let arr = [10, 20, 30];
console.log(0 in arr); // true (index)
console.log(3 in arr); // false
console.log("length" in arr); // true
# Python
person = {"name": "Alice", "age": 30}
print("name" in person) # True
print("salary" in person) # False
# Lists
arr = [10, 20, 30]
print(10 in arr) # True (value, not index)
Ternary/Conditional Operator
The ternary operator is a shorthand for if-else statements.
Basic Ternary
// JavaScript let age = 18; let status = age >= 18 ? "Adult" : "Minor"; console.log(status); // "Adult" // Nested ternary let grade = 85; let letter = grade >= 90 ? "A" : grade >= 80 ? "B" : grade >= 70 ? "C" : grade >= 60 ? "D" : "F"; console.log(letter); // "B"
# Python age = 18 status = "Adult" if age >= 18 else "Minor" print(status) # "Adult" # Nested ternary (use sparingly) grade = 85 letter = "A" if grade >= 90 else \ "B" if grade >= 80 else \ "C" if grade >= 70 else \ "D" if grade >= 60 else "F" print(letter) # "B"
Practical Usage
// Conditional function calls
let isLoggedIn = true;
isLoggedIn ? showDashboard() : showLogin();
// Conditional rendering (React)
return (
<div>
{isLoading ? <Spinner /> : <Content />}
</div>
);
// Default values
let name = inputName ? inputName : "Guest";
let name = inputName || "Guest"; // Alternative with OR
Operator Precedence
Operator precedence determines the order in which operations are evaluated.
Precedence Table (Highest to Lowest)
// JavaScript precedence console.log(2 + 3 * 4); // 14 (multiplication first) console.log((2 + 3) * 4); // 20 (parentheses first) // Full precedence order (simplified): // 1. () - Parentheses // 2. ** - Exponentiation // 3. * / % - Multiplication, Division, Remainder // 4. + - - Addition, Subtraction // 5. << >> >>> - Bitwise shifts // 6. < <= > >= - Relational // 7. == != === !== - Equality // 8. & - Bitwise AND // 9. ^ - Bitwise XOR // 10. | - Bitwise OR // 11. && - Logical AND // 12. || - Logical OR // 13. ?? - Nullish coalescing // 14. ? : - Ternary // 15. = += -= etc. - Assignment
Associativity
// Left-associative (most operators) console.log(10 - 5 - 2); // (10 - 5) - 2 = 3 // Right-associative (exponentiation, assignment) console.log(2 ** 3 ** 2); // 2 ** (3 ** 2) = 512 let a = b = c = 5; // Right-associative
Operator Overloading
Operator overloading allows custom behavior for operators with user-defined types.
Python Operator Overloading
# Python - operator overloading with magic methods
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __sub__(self, other):
return Vector(self.x - other.x, self.y - other.y)
def __mul__(self, scalar):
return Vector(self.x * scalar, self.y * scalar)
def __eq__(self, other):
return self.x == other.x and self.y == other.y
def __repr__(self):
return f"Vector({self.x}, {self.y})"
v1 = Vector(2, 3)
v2 = Vector(4, 5)
print(v1 + v2) # Vector(6, 8)
print(v1 - v2) # Vector(-2, -2)
print(v1 * 3) # Vector(6, 9)
print(v1 == v2) # False
JavaScript Operator Overloading (No direct support)
// JavaScript - no operator overloading
class Vector {
constructor(x, y) {
this.x = x;
this.y = y;
}
add(other) {
return new Vector(this.x + other.x, this.y + other.y);
}
toString() {
return `Vector(${this.x}, ${this.y})`;
}
}
let v1 = new Vector(2, 3);
let v2 = new Vector(4, 5);
console.log(v1.add(v2).toString()); // Vector(6, 8)
Special Operators
Spread Operator
// JavaScript - spread operator (...)
// Arrays
let arr1 = [1, 2, 3];
let arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]
let copy = [...arr1]; // Shallow copy
// Objects
let obj1 = { a: 1, b: 2 };
let obj2 = { ...obj1, c: 3 }; // { a: 1, b: 2, c: 3 }
// Function calls
let numbers = [1, 2, 3, 4, 5];
let max = Math.max(...numbers); // 5
# Python - unpacking operator (* and **)
# Lists/tuples
arr1 = [1, 2, 3]
arr2 = [*arr1, 4, 5] # [1, 2, 3, 4, 5]
copy = [*arr1] # Shallow copy
# Dictionaries
dict1 = {"a": 1, "b": 2}
dict2 = {**dict1, "c": 3} # {"a": 1, "b": 2, "c": 3}
# Function calls
numbers = [1, 2, 3, 4, 5]
print(*numbers) # 1 2 3 4 5
Optional Chaining
// JavaScript - optional chaining (?.)
let user = {
profile: {
name: "Alice"
}
};
console.log(user?.profile?.name); // "Alice"
console.log(user?.address?.city); // undefined (no error)
console.log(user?.nonExistent?.value); // undefined
// With function calls
let obj = {
method: () => "result"
};
console.log(obj.method?.()); // "result"
console.log(obj.noMethod?.()); // undefined
Nullish Coalescing
// JavaScript - nullish coalescing (??) let value = null ?? "default"; // "default" let value2 = undefined ?? "default"; // "default" let value3 = 0 ?? "default"; // 0 let value4 = "" ?? "default"; // "" let value5 = false ?? "default"; // false // Unlike OR (||) which treats falsy values as default let orValue = 0 || "default"; // "default"
Pipeline Operator
// JavaScript (proposal) - pipeline operator (|>)
// Not yet widely supported
// const result = "Hello" |> toUpperCase |> split('') |> reverse |> join('');
// Current approach with chaining
const result = "Hello".toUpperCase().split('').reverse().join('');
Short-Circuit Evaluation
Logical operators use short-circuit evaluation to optimize performance and enable conditional execution.
AND (&&) Short-Circuit
// JavaScript - && stops at first falsy value console.log(false && expensiveFunction()); // false (expensiveFunction not called) // Common pattern: conditional execution isLoggedIn && showDashboard(); // Only calls showDashboard if isLoggedIn is true
# Python
def expensive_function():
print("Called!")
return True
print(False and expensive_function()) # False (function not called)
OR (||) Short-Circuit
// JavaScript - || stops at first truthy value console.log(true || expensiveFunction()); // true (function not called) // Common pattern: default values let name = userInput || "Guest";
Nullish Coalescing (??) Short-Circuit
// JavaScript - ?? stops at first non-null/undefined let value = null ?? expensiveFunction(); // expensiveFunction called let value2 = 0 ?? expensiveFunction(); // 0 (function not called)
Common Pitfalls
1. Floating Point Precision
// JavaScript console.log(0.1 + 0.2); // 0.30000000000000004 console.log(0.1 + 0.2 === 0.3); // false // Solution: use tolerance const EPSILON = 0.000001; console.log(Math.abs((0.1 + 0.2) - 0.3) < EPSILON); // true
# Python
print(0.1 + 0.2) # 0.30000000000000004
# Solution
from decimal import Decimal
print(Decimal('0.1') + Decimal('0.2')) # 0.3
2. Loose vs Strict Equality
// JavaScript console.log(5 == "5"); // true (type coercion) console.log(5 === "5"); // false (strict) console.log(0 == false); // true console.log(0 === false);// false // Best practice: use === always
3. Assignment vs Comparison
// JavaScript - common mistake
if (x = 5) { // Assignment, not comparison!
// Always executes (5 is truthy)
}
// Correct
if (x === 5) { // Comparison
}
# Python - assignment not allowed in if # if x = 5: # SyntaxError! if x == 5: # Correct pass
4. NaN Comparisons
// JavaScript
console.log(NaN === NaN); // false
console.log(isNaN(NaN)); // true
// Number.isNaN is more reliable
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN("abc")); // false (string not converted)
5. Integer Division
// JavaScript - always floating point console.log(5 / 2); // 2.5 // For integer division console.log(Math.floor(5 / 2)); // 2 console.log(5 >> 1); // 2 (bitwise)
// Java - integer division truncates int x = 5 / 2; // 2 double y = 5.0 / 2; // 2.5
Interview Questions
Q1: What's the difference between == and === in JavaScript?
// == compares values after type coercion console.log(5 == "5"); // true console.log(0 == false); // true console.log(null == undefined); // true // === compares values without type coercion console.log(5 === "5"); // false console.log(0 === false); // false console.log(null === undefined); // false // Best practice: always use === for predictable behavior
Q2: What will this output?
console.log(1 + "2" + "2"); // "122"
console.log(1 + +"2" + "2"); // "32"
console.log(1 + -"1" + "2"); // "02"
console.log(+"1" + "1" + "2"); // "112"
console.log("A" - "B" + "2"); // "NaN2"
console.log("A" - "B" + 2); // NaN
// Explanation:
// +"2" converts "2" to number 2
// -"1" converts "1" to number -1
// "A" - "B" results in NaN
Q3: What's the output of this code?
let x = 5; console.log(x++); // 5 console.log(++x); // 7 console.log(x); // 7
Q4: How does short-circuit evaluation work?
// AND (&&) - returns first falsy or last truthy console.log(0 && 5); // 0 console.log(5 && 10); // 10 console.log(5 && 10 && 0 && 20); // 0 // OR (||) - returns first truthy or last falsy console.log(0 || 5); // 5 console.log(5 || 10); // 5 console.log(0 || "" || null); // null // Practical use let user = getUser() || defaultUser; // Default value isAdmin && showAdminPanel(); // Conditional execution
Q5: Explain the difference between & and && in JavaScript?
// & is bitwise AND (operates on binary representation) console.log(5 & 3); // 1 (0101 & 0011 = 0001) // && is logical AND (operates on truthiness) console.log(5 && 3); // 3 (short-circuits, returns last truthy) // For booleans console.log(true & true); // 1 (numeric) console.log(true && true); // true (boolean)
Q6: What will this Python code output?
x = 5 y = 3 print(x / y) # 1.666... print(x // y) # 1 print(x % y) # 2 print(x ** y) # 125 print(x == y) # False print(x != y) # True
Q7: Explain the difference between is and == in Python?
# == compares values a = [1, 2, 3] b = [1, 2, 3] print(a == b) # True (same values) print(a is b) # False (different objects) # is compares identity (memory location) c = a print(a is c) # True (same object) # With small integers (caching) x = 256 y = 256 print(x is y) # True (cached) x = 257 y = 257 print(x is y) # False (not cached)
Conclusion
Operators are fundamental building blocks of programming that allow us to manipulate data, make decisions, and control program flow.
Key Takeaways
| Category | Operators | Use Case |
|---|---|---|
| Arithmetic | +, -, *, /, %, ** | Mathematical calculations |
| Assignment | =, +=, -=, *=, /= | Variable assignment |
| Comparison | ==, ===, !=, !==, <, >, <=, >= | Value comparison |
| Logical | &&, ||, ! | Boolean logic |
| Bitwise | &, |, ^, ~, <<, >> | Bit manipulation |
| Ternary | condition ? a : b | Conditional expressions |
Best Practices
- Use strict equality (
===in JS) to avoid type coercion surprises - Understand short-circuit evaluation for conditional execution
- Be aware of floating point precision issues
- Use parentheses to make precedence explicit
- Avoid complex expressions - break them down for readability
- Consider operator overload in languages that support it
- Use bitwise operators carefully (mostly for flags and low-level operations)
Quick Reference
// Common operator patterns // Default values let name = input || "Guest"; // Conditional execution isValid && doSomething(); // Increment/Decrement let i = 0; i++; // post-increment ++i; // pre-increment // Bitwise flags const READ = 1 << 0; const WRITE = 1 << 1; let permissions = READ | WRITE; // Ternary let status = age >= 18 ? "adult" : "minor";
Understanding operators is essential for writing efficient and expressive code. Master these concepts to become a more effective programmer!