JavaScript Operators: A Detailed Guide

Explore JavaScript operators with Edulane. Learn to use arithmetic, comparison, logical, and other operators effectively in your code. Perfect for all skill levels.

Table of contents

  1. Introduction to JavaScript Operators
  2. Types of JavaScript Operators
    1. Arithmetic Operators
    2. Assignment Operators
    3. Logical Operators
    4. Bitwise Operators
    5. String Operators
    6. Conditional (Ternary) Operator
    7. Comma Operator
    8. Unary Operators
    9. Relational Operators
    10. Type Operators
  3. Interview Questions
  4. Practice Exercises

Introduction to JavaScript Operators

Learning JavaScript operators is crucial because they form the backbone of how you manipulate data and control the flow of logic in your JavaScript programs. Here are some key reasons why learning operators is important:

  1. Data Manipulation: Operators allow you to perform arithmetic operations (like addition, subtraction, etc.) and manipulate values stored in variables. This is essential for performing calculations and processing data in your applications.
  2. Conditional Logic: Comparison and logical operators are fundamental for implementing conditional logic (if statements, loops, etc.). They help you make decisions based on conditions, which is crucial for controlling the flow of your program.
  3. Efficiency: Using operators efficiently can make your code more concise and readable. For instance, shorthand assignment operators (+=, -=, etc.) save you from writing repetitive code.
  4. Understanding Code: When you read JavaScript code written by others or in libraries/frameworks, understanding how operators are used helps you comprehend what the code is doing. It enables you to debug and modify code effectively.
  5. Expressiveness: JavaScript operators provide expressive power to your code. For example, the ternary operator (condition ? expr1 : expr2) allows you to write conditional expressions concisely.
  6. Compatibility: JavaScript operators are universal across all platforms and browsers that support JavaScript. Understanding them ensures your code works consistently across different environments.
  7. Foundation for Advanced Concepts: Mastery of operators forms the basis for understanding more advanced JavaScript concepts like functions, objects, arrays, and more complex control structures.

In summary, operators in JavaScript are fundamental tools for manipulating data, implementing logic, and building efficient and readable code. They are essential for anyone looking to write JavaScript code effectively, whether for front-end web development, back-end server scripting, or other applications.

Types of JavaScript Operators

TypesDesceription
Arithmetic OperatorsArithmetic operators are used to perform arithmetic on numbers.
Assignment OperatorsAssignment operators assign values to JavaScript variables.
Comparison OperatorsComparison operators compare two values and return a boolean value (true or false).
Logical OperatorsLogical operators are used to determine the logic between variables or values.
Bitwise OperatorsBitwise operators treat their operands as a set of 32 bits (zeros and ones) and perform actions at the bit level.
String OperatorsString operators are used to concatenate (join) strings.
Conditional (Ternary) OperatorThe conditional (ternary) operator assigns a value to a variable based on a condition.
Comma OperatorThe comma operator allows you to evaluate multiple expressions in a single statement.
Unary OperatorsUnary operators operate on a single operand to produce a result.
Relational OperatorsRelational operators determine the relationship between two values.
Type OperatorsType operators are used to identify the data type of a value.

Arithmetic Operators

JavaScript provides several arithmetic operators for performing basic mathematical operations.

OperatorDescriptionExampleResult
+The Addition operator (+) is used to add two numbers5 + 27
-Subtraction operator (-) subtracts the second number from the first5 - 23
*Multiplication (*) multiplies two numbers5 * 210
/Division (/) divides the first number by the second5 / 22.5
%The Modulus operator (%) returns the remainder of a division, useful for checking even or odd numbers.5 % 21
++Increment (++) increases a number by 1, and it can be used in both prefix (e.g., ++i) and postfix (e.g., i++) forms, with the prefix incrementing before and the postfix incrementing after the operation.let a = 5; a++6 (a becomes 6)
--The decrement operator (--) decreases a number by 1 and can also be used in both prefix (--i) and postfix (i--) forms, with the prefix decrementing before and the postfix decrementing after the operation. Using these operators, JavaScript can handle a wide range of arithmetic operations efficiently.let a = 5; a--4 (a becomes 4)
**Exponentiation (**) raises the first number to the power of the second, providing a way to perform power calculations.5 ** 225
Explanation with Code
/*
  JavaScript Arithmetic Operators:
  - Addition (+)
  - Subtraction (-)
  - Multiplication (*)
  - Division (/)
  - Modulus (%)
  - Exponentiation (**)
  - Increment (++)
  - Decrement (--)
*/

// Addition (+)
// Adds two numbers.
let sum = 10 + 5; // 15
console.log(`10 + 5 = ${sum}`);

// Best practice: Use parentheses to ensure clarity in complex expressions.
let complexSum = (10 + 5) + (3 + 2); // 20
console.log(`(10 + 5) + (3 + 2) = ${complexSum}`);

// Subtraction (-)
// Subtracts the second number from the first.
let difference = 10 - 5; // 5
console.log(`10 - 5 = ${difference}`);

// Multiplication (*)
// Multiplies two numbers.
let product = 10 * 5; // 50
console.log(`10 * 5 = ${product}`);

// Division (/)
// Divides the first number by the second.
let quotient = 10 / 5; // 2
console.log(`10 / 5 = ${quotient}`);

// Best practice: Check for division by zero to avoid errors.
let divisor = 0;
if (divisor !== 0) {
  let safeQuotient = 10 / divisor;
  console.log(`10 / ${divisor} = ${safeQuotient}`);
} else {
  console.log("Division by zero is not allowed.");
}

// Modulus (%)
// Returns the remainder of a division.
let remainder = 10 % 3; // 1
console.log(`10 % 3 = ${remainder}`);

// Best practice: Use modulus for even/odd checks.
let number = 10;
if (number % 2 === 0) {
  console.log(`${number} is even`);
} else {
  console.log(`${number} is odd`);
}

// Exponentiation (**)
// Raises the first number to the power of the second.
let power = 10 ** 2; // 100
console.log(`10 ** 2 = ${power}`);

// Increment (++)
// Increases a number by 1.
let increment = 10;
increment++; // 11
console.log(`10 incremented by 1 is ${increment}`);

// Best practice: Be aware of prefix (++i) vs postfix (i++) increment.
let prefixIncrement = 10;
let prefixResult = ++prefixIncrement; // 11, prefix increments before assignment
console.log(`Prefix Increment: ++10 = ${prefixResult}`);

let postfixIncrement = 10;
let postfixResult = postfixIncrement++; // 10, postfix increments after assignment
console.log(`Postfix Increment: 10++ = ${postfixResult}`);
console.log(`Postfix Increment result: ${postfixIncrement}`); // 11

// Decrement (--)
// Decreases a number by 1.
let decrement = 10;
decrement--; // 9
console.log(`10 decremented by 1 is ${decrement}`);

// Best practice: Be aware of prefix (--i) vs postfix (i--) decrement.
let prefixDecrement = 10;
let prefixDecrementResult = --prefixDecrement; // 9, prefix decrements before assignment
console.log(`Prefix Decrement: --10 = ${prefixDecrementResult}`);

let postfixDecrement = 10;
let postfixDecrementResult = postfixDecrement--; // 10, postfix decrements after assignment
console.log(`Postfix Decrement: 10-- = ${postfixDecrementResult}`);
console.log(`Postfix Decrement result: ${postfixDecrement}`); // 9

/*
  Best Practices Summary:
  - Use parentheses to ensure clarity and correct order of operations.
  - Avoid division by zero to prevent errors.
  - Be mindful of prefix and postfix increment/decrement operations and their effects on expressions.
*/

Assignment Operators

Assignment operators in JavaScript perform operations on variables and assign the result to the variable, including basic assignment (=), arithmetic (+=, -=, *=, /=, %=, **=), and bitwise (&=, |=, ^=, <<=, >>=, >>>=).

OperatorDescriptionExampleResult
=Assigns the value on the right to the variable on the left.let a = 10;a is 10
+=Adds the value on the right to the variable on the left and assigns the result to the variable.a += 5;a is 15
-=Subtracts the value on the right from the variable on the left and assigns the result to the variable.a -= 3;a is 12
*=Multiplies the variable on the left by the value on the right and assigns the result to the variable.a *= 2;a is 24
/=Divides the variable on the left by the value on the right and assigns the result to the variable.a /= 4;a is 6
%=Divides the variable on the left by the value on the right and assigns the remainder to the variable.a %= 5;a is 1
**=Raises the variable on the left to the power of the value on the right and assigns the result to the variable.a **= 3;a is 1
&=Performs a bitwise AND on the variable and the value, and assigns the result to the variable.a &= 2;a is 0
`=`Performs a bitwise OR on the variable and the value, and assigns the result to the variable.`a
^=Performs a bitwise XOR on the variable and the value, and assigns the result to the variable.a ^= 2;a is 0
<<=Shifts the bits of the variable to the left by the value and assigns the result to the variable.a <<= 1;a is 0
>>=Shifts the bits of the variable to the right by the value and assigns the result to the variable.a >>= 1;a is 0
>>>=Shifts the bits of the variable to the right by the value (fills leftmost bits with 0) and assigns the result to the variable.a >>>= 1;a is 0
Explanation with Code
// JavaScript Assignment Operators with Examples and Best Practices

// 1. Assignment Operator (=)
// Assigns the value on the right to the variable on the left.
let a = 10;  // a is now 10

// 2. Addition Assignment Operator (+=)
// Adds the value on the right to the variable on the left and assigns the result to the variable.
let b = 5;
b += 3;  // b is now 8 (5 + 3)

// Best Practice: Use += to accumulate values in a loop
let sum = 0;
for (let i = 1; i <= 5; i++) {
    sum += i;  // sum is 15 after the loop (1 + 2 + 3 + 4 + 5)
}

// 3. Subtraction Assignment Operator (-=)
// Subtracts the value on the right from the variable on the left and assigns the result to the variable.
let c = 10;
c -= 4;  // c is now 6 (10 - 4)

// Best Practice: Use -= to decrement values in loops
let countdown = 10;
while (countdown > 0) {
    countdown -= 1;  // countdown reaches 0
}

// 4. Multiplication Assignment Operator (*=)
// Multiplies the variable on the left by the value on the right and assigns the result to the variable.
let d = 4;
d *= 3;  // d is now 12 (4 * 3)

// 5. Division Assignment Operator (/=)
// Divides the variable on the left by the value on the right and assigns the result to the variable.
let e = 20;
e /= 4;  // e is now 5 (20 / 4)

// 6. Remainder Assignment Operator (%=)
// Divides the variable on the left by the value on the right and assigns the remainder to the variable.
let f = 10;
f %= 3;  // f is now 1 (10 % 3)

// 7. Exponentiation Assignment Operator (**=)
// Raises the variable on the left to the power of the value on the right and assigns the result to the variable.
let g = 2;
g **= 3;  // g is now 8 (2^3)

// 8. Bitwise AND Assignment Operator (&=)
// Performs a bitwise AND on the variable and the value, and assigns the result to the variable.
let h = 5;   // binary: 0101
h &= 3;      // binary: 0011, result: 0001 (1 in decimal)

// 9. Bitwise OR Assignment Operator (|=)
// Performs a bitwise OR on the variable and the value, and assigns the result to the variable.
let i = 5;   // binary: 0101
i |= 3;      // binary: 0011, result: 0111 (7 in decimal)

// 10. Bitwise XOR Assignment Operator (^=)
// Performs a bitwise XOR on the variable and the value, and assigns the result to the variable.
let j = 5;   // binary: 0101
j ^= 3;      // binary: 0011, result: 0110 (6 in decimal)

// 11. Left Shift Assignment Operator (<<=)
// Shifts the bits of the variable to the left by the value and assigns the result to the variable.
let k = 5;   // binary: 0101
k <<= 2;     // binary: 010100, result: 20 in decimal

// 12. Right Shift Assignment Operator (>>=)
// Shifts the bits of the variable to the right by the value and assigns the result to the variable.
let l = 20;  // binary: 10100
l >>= 2;     // binary: 00101, result: 5 in decimal

// 13. Unsigned Right Shift Assignment Operator (>>>=)
// Shifts the bits of the variable to the right by the value (fills leftmost bits with 0) and assigns the result to the variable.
let m = -20; // binary: -10100
m >>>= 2;    // binary: 00101, result: a large positive integer due to unsigned shift

// Best Practices:
// 1. Use assignment operators to make your code concise and readable.
// 2. Always initialize variables before using assignment operators to avoid unexpected results.
// 3. Comment your code to explain the use of complex assignment operators, especially bitwise operators.
// 4. Test your code to ensure that assignment operations produce the expected results.

console.log({a, b, c, d, e, f, g, h, i, j, k, l, m});  // Output the final values for verification

Comparison Operators

Comparison operators compare two values and return a boolean value (true or false).

OperatorDescriptionExampleResult
==Equal to5 == 2false
===Equal value and equal type5 === 5true
!=Not equal5 != 2true
!==Not equal value or not equal type5 !== “5”true
>Greater than5 > 2true
<Less than5 < 2false
>=Greater than or equal to5 >= 2true
<=Less than or equal to5 <= 2false
// JavaScript Comparison Operators Explained

// 1. Equal (==)
// Compares two values for equality after converting both values to a common type.
let a = 5;
let b = '5';
console.log(a == b); // true, because '5' is converted to 5 before comparison

// Best Practice: Avoid using == because it performs type coercion. Use === instead.

// 2. Strict Equal (===)
// Compares two values for equality without converting their types.
console.log(a === b); // false, because a is number and b is string

// 3. Not Equal (!=)
// Compares two values for inequality after converting both values to a common type.
let c = 10;
let d = '10';
console.log(c != d); // false, because '10' is converted to 10 before comparison

// Best Practice: Avoid using != because it performs type coercion. Use !== instead.

// 4. Strict Not Equal (!==)
// Compares two values for inequality without converting their types.
console.log(c !== d); // true, because c is number and d is string

// 5. Greater Than (>)
// Checks if the left operand is greater than the right operand.
let e = 15;
let f = 10;
console.log(e > f); // true

// 6. Greater Than or Equal (>=)
// Checks if the left operand is greater than or equal to the right operand.
console.log(e >= f); // true

// 7. Less Than (<)
// Checks if the left operand is less than the right operand.
let g = 5;
console.log(g < f); // true

// 8. Less Than or Equal (<=)
// Checks if the left operand is less than or equal to the right operand.
console.log(g <= f); // true

// Best Practices for Comparison Operators:
// - Always use strict equality (===) and strict inequality (!==) to avoid unexpected type coercion.
// - Be mindful of JavaScript's type coercion when using == and !=.
// - When comparing different types, explicitly convert them to the same type for clarity.

// Example of explicit type conversion:
let h = '20';
let i = 20;
console.log(Number(h) === i); // true, because '20' is converted to 20 before comparison

// Edge Case Examples:

// Comparing objects and arrays
let obj1 = { name: 'Alice' };
let obj2 = { name: 'Alice' };
console.log(obj1 === obj2); // false, because objects are compared by reference, not value

let arr1 = [1, 2, 3];
let arr2 = [1, 2, 3];
console.log(arr1 === arr2); // false, because arrays are compared by reference, not value

// Comparing null and undefined
console.log(null == undefined); // true, both are considered equal in non-strict comparison
console.log(null === undefined); // false, because their types are different

// NaN (Not-a-Number) comparisons
let nanValue = NaN;
console.log(nanValue === NaN); // false, NaN is not equal to anything, including itself
console.log(isNaN(nanValue)); // true, use isNaN() to check for NaN

// Comparing strings
let str1 = 'hello';
let str2 = 'world';
console.log(str1 < str2); // true, because 'h' comes before 'w' lexicographically

Logical Operators

Logical operators are used to determine the logic between variables or values.

OperatorDescriptionExampleResult
&&Logical ANDtrue && falsefalse
||Logical ORtrue || falsetrue
!Logical NOT!truefalse
// JavaScript Logical Operators - Detailed Explanation and Best Practices

// Logical AND (&&) Operator
// The && operator returns true if both operands are true. If one of them is false, it returns false.

const isAdult = true;
const hasID = true;

const canEnterClub = isAdult && hasID; // true because both conditions are true

// Best Practice: Use short-circuit evaluation to check for null or undefined before accessing properties.
const user = { name: 'Alice' };
const userName = user && user.name; // 'Alice', user is not null/undefined

// Logical OR (||) Operator
// The || operator returns true if at least one of the operands is true. If both are false, it returns false.

const hasDriverLicense = false;
const hasPassport = true;

const canTravel = hasDriverLicense || hasPassport; // true because one condition is true

// Best Practice: Use || to provide default values.
const inputName = '';
const defaultName = inputName || 'Guest'; // 'Guest', because inputName is falsy (empty string)

// Logical NOT (!) Operator
// The ! operator negates the value of its operand. If the operand is true, it returns false and vice versa.

const isRaining = false;
const isSunny = !isRaining; // true because !false is true

// Best Practice: Use double negation (!!) to convert a value to a boolean.
const value = 'some text';
const isValueTruthy = !!value; // true because 'some text' is truthy

// Combined Logical Operators
// You can combine logical operators to form complex logical expressions.

const isWeekend = true;
const isHoliday = false;
const canRelax = (isWeekend || isHoliday) && !hasWork;

// canRelax is true because it's weekend and no work.

// Best Practice: Use parentheses to make complex expressions readable.
const age = 25;
const hasParentalConsent = false;
const canWatchMovie = (age >= 18 || hasParentalConsent) && !isRestricted;

// canWatchMovie is true because age is 25 (>= 18) and not restricted.

// Short-Circuit Evaluation
// Logical operators use short-circuit evaluation, meaning they stop evaluating as soon as the result is determined.

const result = false && (console.log('This will not log'), true); // false
const output = true || (console.log('This will not log'), false); // true

// Best Practice: Avoid side effects in logical expressions for clarity and maintainability.

// Common Pitfalls and Tips
// - Avoid using logical operators for control flow (if-else) to maintain readability.
const value1 = true && true; // Use explicit if statements for control flow instead
if (isAdult && hasID) {
  console.log('You can enter the club');
}

// - Remember that non-boolean values are coerced to boolean in logical expressions.
// Truthy values include: non-zero numbers, non-empty strings, objects, arrays, etc.
// Falsy values include: 0, '', null, undefined, NaN, false.
const emptyArray = [];
const nonEmptyArray = [1, 2, 3];
console.log(!emptyArray); // false, because emptyArray is truthy
console.log(!nonEmptyArray); // false, because nonEmptyArray is truthy

// - Use logical operators to simplify conditions and avoid deeply nested if-else structures.

const hasAdminAccess = true;
const isOwner = false;

if (hasAdminAccess || isOwner) {
  console.log('You have access');
} else {
  console.log('Access denied');
}

// Summary:
// - && returns true if both operands are true.
// - || returns true if at least one operand is true.
// - ! negates the value of its operand.
// - Use short-circuit evaluation for efficiency and default values.
// - Keep logical expressions readable and maintainable.

Bitwise Operators

Bitwise operators treat their operands as a set of 32 bits (zeros and ones) and perform actions at the bit level.

OperatorDescriptionExampleResult
&AND5 & 11
|OR5 | 15
^XOR5 ^ 14
~NOT~5-6
<<Zero fill left shift5 << 110
>>Signed right shift5 >> 12
>>>Zero fill right shift5 >>> 12
/*
  JavaScript Bitwise Operators - Detailed Explanation and Examples

  Bitwise operators treat their operands as a set of 32 bits (binary digits),
  rather than as decimal, hexadecimal, or octal numbers. 
  They operate on each bit of a number's binary representation.

  Bitwise Operators:
  1. AND (&)
  2. OR (|)
  3. XOR (^)
  4. NOT (~)
  5. LEFT SHIFT (<<)
  6. SIGNED RIGHT SHIFT (>>)
  7. UNSIGNED RIGHT SHIFT (>>>)

  Best Practices:
  - Ensure operands are integers.
  - Use bitwise operators for performance-critical code.
  - Be cautious with large numbers as JavaScript bitwise operations are done on 32-bit integers.
  - Avoid using bitwise operators with floating-point numbers.
*/

// 1. AND (&)
// Sets each bit to 1 if both bits are 1.
let a = 5; // 0101 in binary
let b = 3; // 0011 in binary
let andResult = a & b; // 0001 in binary (1 in decimal)
console.log(`AND Operation: ${a} & ${b} = ${andResult}`); // Output: AND Operation: 5 & 3 = 1

// 2. OR (|)
// Sets each bit to 1 if one of the bits is 1.
let orResult = a | b; // 0111 in binary (7 in decimal)
console.log(`OR Operation: ${a} | ${b} = ${orResult}`); // Output: OR Operation: 5 & 3 = 7

// 3. XOR (^)
// Sets each bit to 1 if only one of the bits is 1.
let xorResult = a ^ b; // 0110 in binary (6 in decimal)
console.log(`XOR Operation: ${a} ^ ${b} = ${xorResult}`); // Output: XOR Operation: 5 ^ 3 = 6

// 4. NOT (~)
// Inverts all the bits.
let notResult = ~a; // 1010 in binary (-6 in decimal, due to two's complement representation)
console.log(`NOT Operation: ~${a} = ${notResult}`); // Output: NOT Operation: ~5 = -6

// 5. LEFT SHIFT (<<)
// Shifts bits to the left and fills 0 on voids left as a result.
let leftShiftResult = a << 1; // 1010 in binary (10 in decimal)
console.log(`Left Shift Operation: ${a} << 1 = ${leftShiftResult}`); // Output: Left Shift Operation: 5 << 1 = 10

// 6. SIGNED RIGHT SHIFT (>>)
// Shifts bits to the right and fills the leftmost bits based on the original number's sign bit.
let rightShiftResult = a >> 1; // 0010 in binary (2 in decimal)
console.log(`Right Shift Operation: ${a} >> 1 = ${rightShiftResult}`); // Output: Right Shift Operation: 5 >> 1 = 2

// 7. UNSIGNED RIGHT SHIFT (>>>)
// Shifts bits to the right and fills the leftmost bits with 0, regardless of the sign bit.
let unsignedRightShiftResult = a >>> 1; // 0010 in binary (2 in decimal)
console.log(`Unsigned Right Shift Operation: ${a} >>> 1 = ${unsignedRightShiftResult}`); // Output: Unsigned Right Shift Operation: 5 >>> 1 = 2

/*
  Best Practices:
  - Always ensure that the operands used with bitwise operators are integers to avoid unexpected results.
  - Bitwise operators are particularly useful in low-level programming, such as graphics manipulation, 
    cryptography, and network programming.
  - When using bitwise operators, remember that JavaScript internally handles numbers as 32-bit signed integers.
  - Avoid using bitwise operators on floating-point numbers or numbers larger than 32 bits, as this can lead 
    to precision issues and unexpected results.
  - Use parentheses to ensure proper precedence and readability.
*/

String Operators

String operators are used to concatenate (join) strings.

OperatorDescriptionExampleResult
+Concatenation"Hello" + " " + "World"“Hello World”
// JavaScript String Operators

// 1. Concatenation Operator (+)
// The concatenation operator is used to combine two or more strings.
let str1 = "Hello";
let str2 = "World";
let concatenatedString = str1 + " " + str2; // "Hello World"
console.log(concatenatedString);

// Best Practice: Use template literals for better readability and performance when dealing with multiple concatenations.
// Example using template literals (introduced in ES6):
let templateString = `${str1} ${str2}`; // "Hello World"
console.log(templateString);

// 2. Assignment with Concatenation Operator (+=)
// This operator appends the right-hand string to the left-hand string.
let str3 = "Hello";
str3 += " World"; // "Hello World"
console.log(str3);

// 3. Comparison Operators (==, ===, !=, !==)
// These operators are used to compare two strings.

// Equality (==): Checks if two strings are equal (type conversion is performed).
console.log("Hello" == "Hello"); // true
console.log("Hello" == "hello"); // false

// Strict Equality (===): Checks if two strings are equal (no type conversion).
console.log("Hello" === "Hello"); // true
console.log("Hello" === "hello"); // false

// Inequality (!=): Checks if two strings are not equal (type conversion is performed).
console.log("Hello" != "hello"); // true

// Strict Inequality (!==): Checks if two strings are not equal (no type conversion).
console.log("Hello" !== "hello"); // true

// Best Practice: Use strict equality (===) and strict inequality (!==) to avoid type conversion issues.

// 4. String Methods
// There are several string methods that can be used to manipulate strings.

// length: Returns the length of the string.
let lengthOfString = str1.length; // 5
console.log(lengthOfString);

// toUpperCase(): Converts the string to uppercase.
let upperCaseString = str1.toUpperCase(); // "HELLO"
console.log(upperCaseString);

// toLowerCase(): Converts the string to lowercase.
let lowerCaseString = str2.toLowerCase(); // "world"
console.log(lowerCaseString);

// substring(start, end): Extracts characters from the string between start and end indices.
let subString = concatenatedString.substring(0, 5); // "Hello"
console.log(subString);

// slice(start, end): Similar to substring but allows negative indices.
let slicedString = concatenatedString.slice(0, 5); // "Hello"
console.log(slicedString);

// indexOf(substring): Returns the index of the first occurrence of the substring, or -1 if not found.
let indexOfWorld = concatenatedString.indexOf("World"); // 6
console.log(indexOfWorld);

// includes(substring): Checks if the string contains the specified substring.
let containsWorld = concatenatedString.includes("World"); // true
console.log(containsWorld);

// split(separator): Splits the string into an array of substrings.
let splitString = concatenatedString.split(" "); // ["Hello", "World"]
console.log(splitString);

// join(separator): Joins an array of strings into a single string.
let joinedString = splitString.join(", "); // "Hello, World"
console.log(joinedString);

// 5. Template Literals
// Template literals allow embedding expressions and multi-line strings.
let name = "John";
let greeting = `Hello, ${name}!`; // "Hello, John!"
console.log(greeting);

// Multi-line strings using template literals:
let multiLineString = `This is a string
that spans multiple
lines.`;
console.log(multiLineString);

// Best Practice: Prefer template literals over string concatenation for better readability and maintainability.

// Conclusion: Understanding and using these string operators and methods effectively can help you write more readable and maintainable JavaScript code.

Conditional (Ternary) Operator

The conditional (ternary) operator assigns a value to a variable based on a condition.

OperatorDescriptionExampleResult
? :Ternary Operator (conditional)let age = 18; let type = (age >= 18) ? “adult” : “minor”;“adult”
/*
  The Conditional (Ternary) Operator is a shorthand way to write an if-else statement. 
  It has the following syntax:
  
  condition ? expressionIfTrue : expressionIfFalse;

  - condition: A boolean expression that evaluates to true or false.
  - expressionIfTrue: The expression to execute if the condition is true.
  - expressionIfFalse: The expression to execute if the condition is false.

  It's called "ternary" because it involves three parts.
*/

// Example 1: Basic Usage
let age = 20;
let canVote = age >= 18 ? 'Yes, you can vote.' : 'No, you cannot vote.';
console.log(canVote); // Output: Yes, you can vote.

/*
  Explanation: 
  The condition (age >= 18) is checked. 
  If it's true, 'Yes, you can vote.' is returned. 
  Otherwise, 'No, you cannot vote.' is returned.
*/

// Example 2: Nested Ternary Operators
let score = 85;
let grade = score >= 90 ? 'A' : score >= 80 ? 'B' : score >= 70 ? 'C' : score >= 60 ? 'D' : 'F';
console.log(grade); // Output: B

/*
  Explanation:
  Here, we use nested ternary operators to assign a grade based on the score.
  This approach, however, can reduce readability if overused. It's often better to use if-else statements for complex conditions.
*/

// Example 3: Assigning Default Values
let userColor = 'blue';
let defaultColor = 'green';
let currentColor = userColor ? userColor : defaultColor;
console.log(currentColor); // Output: blue

/*
  Explanation:
  The ternary operator checks if userColor is truthy. If it is, userColor is assigned to currentColor. Otherwise, defaultColor is assigned.
*/

// Example 4: Ternary Operator with Function Calls
function greet(isMorning) {
  return isMorning ? 'Good morning!' : 'Good evening!';
}
console.log(greet(true));  // Output: Good morning!
console.log(greet(false)); // Output: Good evening!

/*
  Explanation:
  The greet function uses the ternary operator to return different greetings based on the isMorning parameter.
*/

// Best Practices:

/*
  1. **Readability**: Ensure the ternary operator is easy to read and understand. Avoid nesting multiple ternary operators.
  2. **Simplicity**: Use the ternary operator for simple conditional assignments. For complex logic, prefer if-else statements.
  3. **Consistency**: Use the ternary operator consistently within your codebase for similar patterns of conditional assignments.
  4. **Avoid Side Effects**: The expressions in the ternary operator should not have side effects (like modifying variables or making function calls that change state).
*/

// Example of Avoiding Side Effects
let count = 0;
let message = (count++, count > 0 ? 'Positive' : 'Non-positive');
console.log(count);   // Output: 1
console.log(message); // Output: Non-positive

/*
  Explanation:
  Although the above code works, using the ternary operator to increment count and evaluate its value can lead to unexpected behavior.
  It's better to separate these operations for clarity and maintainability.
*/

Comma Operator

The comma operator allows you to evaluate multiple expressions in a single statement.

OperatorDescriptionExampleResult
,Comma Operatorlet a = 1, b = 2, c = a + b;a = 1, b = 2, c = 3
// The comma operator in JavaScript

// 1. Basic Usage
// The comma operator evaluates each of its operands and returns the value of the last operand.
// This can be useful in situations where multiple expressions are needed but only one value is expected.

// Example:
let x = (1, 2, 3);
console.log(x); // Output: 3
// Explanation: The comma operator evaluates 1, then 2, then 3, and returns the last value, which is 3.

// 2. Inside a for loop
// The comma operator can be used to include multiple statements in the initialization or increment sections of a for loop.

// Example:
for (let i = 0, j = 10; i < 5; i++, j -= 2) {
    console.log(`i: ${i}, j: ${j}`);
}
// Explanation: The loop initializes i to 0 and j to 10. In each iteration, it increments i by 1 and decrements j by 2.
// Output:
// i: 0, j: 10
// i: 1, j: 8
// i: 2, j: 6
// i: 3, j: 4
// i: 4, j: 2

// 3. With Assignment
// You can use the comma operator to perform multiple assignments in a single statement.

// Example:
let a, b;
a = (b = 5, b + 2); // b is assigned 5, then b + 2 is evaluated and assigned to a
console.log(a); // Output: 7
console.log(b); // Output: 5
// Explanation: The expression b = 5 assigns 5 to b. The comma operator then evaluates b + 2, which is 7, and assigns it to a.

// 4. In Function Arguments
// The comma operator can be used in function arguments to include multiple expressions.

// Example:
function example(x, y) {
    console.log(x, y);
}

example((1, 2), (3, 4)); // Output: 2 4
// Explanation: In the function call, (1, 2) evaluates to 2 and (3, 4) evaluates to 4. Thus, the function receives 2 and 4 as arguments.

// Best Practices:
// - Use the comma operator sparingly. Overusing it can make code less readable.
// - Ensure that using the comma operator does not obscure the logic of your code.
// - Prefer using more explicit constructs (like separate statements or clearer code structures) when readability is a concern.

// Overall, the comma operator is a useful tool in JavaScript, but it should be used thoughtfully to avoid confusion.

Unary Operators

Unary operators operate on a single operand to produce a result.

OperatorDescriptionExampleResult
typeofReturns the type of a variabletypeof 42“number”
+Unary plus+ “3”3
-Unary negation- - “3”-3
++Incrementlet a = 5; ++a6
--Decrementlet a = 5; --a4
!Logical NOT!truefalse
deleteDeletes an object propertydelete obj.propertytrue (if succeeded)
voidDiscards a return valuevoid 0undefined
// Unary Operators in JavaScript

// 1. Unary Plus (+)
// The unary plus operator converts its operand to a number.

let str = "42";
let num = +str; // Converts the string "42" to the number 42
console.log(num); // Output: 42

// Best Practice: Use unary plus when you want to ensure a value is a number, especially from strings.

// 2. Unary Negation (-)
// The unary negation operator converts its operand to a number and then negates it.

let positive = 5;
let negative = -positive; // Negates the number 5 to -5
console.log(negative); // Output: -5

// Best Practice: Use unary negation to quickly invert the sign of a number.

// 3. Logical NOT (!)
// The logical NOT operator converts its operand to a boolean value and then negates it.

let truthyValue = "hello";
let falsyValue = !truthyValue; // Converts "hello" to true, then negates to false
console.log(falsyValue); // Output: false

// Best Practice: Use logical NOT to convert values to boolean or to negate a boolean value.

// 4. Increment (++)
// The increment operator increases the value of its operand by 1.

let count = 0;
count++; // Increases count by 1
console.log(count); // Output: 1

// Best Practice: Use increment operators in loops or when you need to increase a value by 1.

// 5. Decrement (--)
// The decrement operator decreases the value of its operand by 1.

let number = 10;
number--; // Decreases number by 1
console.log(number); // Output: 9

// Best Practice: Use decrement operators in loops or when you need to decrease a value by 1.

// 6. Unary Negation of Non-Numbers
// Unary negation will convert non-numeric values to NaN (Not-a-Number).

let notANumber = -"hello"; // Converts "hello" to NaN
console.log(notANumber); // Output: NaN

// Best Practice: Avoid using unary negation on non-numeric values unless you are specifically testing for NaN.

// 7. Unary Plus with Non-Numbers
// Unary plus also converts non-numeric values to NaN, similar to unary negation.

let notANum = +"world"; // Converts "world" to NaN
console.log(notANum); // Output: NaN

// Best Practice: As with unary negation, be cautious using unary plus with non-numeric values if not intended.

// Conclusion:
// Unary operators provide concise ways to manipulate values in JavaScript.
// Use them judiciously to ensure code readability and maintainability.
Explanation:
  1. Unary Plus (+): Converts its operand to a number.
  2. Unary Negation (-): Converts its operand to a number and negates it.
  3. Logical NOT (!): Converts its operand to a boolean and then negates it.
  4. Increment (++): Increases the value by 1.
  5. Decrement (--): Decreases the value by 1.
Best Practices:
  • Use unary plus for converting strings to numbers.
  • Use unary negation for negating numbers.
  • Use logical NOT for converting values to boolean or negating boolean values.
  • Use increment and decrement operators for concise modifications of numerical values.

Relational Operators

Relational operators determine the relationship between two values.

OperatorDescriptionExampleResult
inProperty in an object“length” in [1, 2, 3]true
instanceofInstance of an objectobj instanceof Objecttrue
// JavaScript Operators: in and instanceof

// 1. `in` Operator
// The `in` operator checks if a specified property exists in an object.

const person = {
  name: 'Alice',
  age: 30,
  city: 'New York'
};

console.log('name' in person); // true, because 'name' is a property of the person object
console.log('age' in person); // true, because 'age' is a property of the person object
console.log('address' in person); // false, because 'address' is not a property of the person object

// Best Practice: Use the `in` operator when you want to check if an object has a specific property,
// regardless of whether the property value is undefined or not.

// 2. `instanceof` Operator
// The `instanceof` operator checks if an object is an instance of a particular class or constructor function.

class Animal {
  constructor(name) {
    this.name = name;
  }
}

class Dog extends Animal {
  bark() {
    console.log('Woof!');
  }
}

const myDog = new Dog('Buddy');

console.log(myDog instanceof Dog); // true, because myDog is an instance of Dog
console.log(myDog instanceof Animal); // true, because Dog extends Animal, so myDog is also an instance of Animal
console.log(myDog instanceof Object); // true, because all objects in JavaScript are instances of Object

// Best Practice: Use `instanceof` to check if an object is an instance of a particular class or constructor function.
// This is especially useful for type checking in object-oriented programming and when working with inheritance.

// Additional Notes:
// - The `in` operator can also be used to check if an index exists in an array.
// - The `instanceof` operator checks the prototype chain for an instance.

const numbers = [1, 2, 3];
console.log(1 in numbers); // true, because index 1 exists in the array (value: 2)
console.log(5 in numbers); // false, because index 5 does not exist in the array

// Custom prototype chain example
function CustomType() {}
const customObj = new CustomType();
console.log(customObj instanceof CustomType); // true
console.log(customObj instanceof Object); // true
Key Points:
  • in Operator: Checks if a property exists in an object or an index exists in an array.
  • instanceof Operator: Checks if an object is an instance of a specific class or constructor function by examining its prototype chain.

These operators are useful for object property checks and type checking in JavaScript.

Type Operators

Type operators are used to identify the data type of a value.

OperatorDescriptionExampleResult
typeofReturns the type of a variabletypeof “hello”“string”
instanceofReturns true if an object is an instance of a specified object[] instanceof Arraytrue
// Type Operators in JavaScript

// 1. typeof Operator
// The typeof operator is used to determine the type of a variable or expression.
// It returns a string representing the type.

let str = "Hello, World!";
let num = 42;
let bool = true;
let obj = { key: "value" };
let arr = [1, 2, 3];
let func = function() {};
let und = undefined;
let n = null;

console.log(typeof str); // "string"
console.log(typeof num); // "number"
console.log(typeof bool); // "boolean"
console.log(typeof obj); // "object"
console.log(typeof arr); // "object" (Arrays are objects in JavaScript)
console.log(typeof func); // "function"
console.log(typeof und); // "undefined"
console.log(typeof n); // "object" (null is considered an object, but this is a quirk)

// Best Practice: Always use typeof with known primitive types
console.log(typeof str === 'string'); // true
console.log(typeof num === 'number'); // true

// 2. instanceof Operator
// The instanceof operator is used to check if an object is an instance of a specific class or constructor function.

console.log(arr instanceof Array); // true
console.log(obj instanceof Object); // true
console.log(func instanceof Function); // true
console.log(num instanceof Number); // false (num is a primitive, not an object)

// Best Practice: Use instanceof for custom object checks
function Person(name) {
    this.name = name;
}

let person = new Person("Alice");
console.log(person instanceof Person); // true

// 3. in Operator
// The in operator is used to check if a property exists in an object or its prototype chain.

console.log("key" in obj); // true (obj has a property 'key')
console.log("length" in arr); // true (Array has a 'length' property)
console.log("toString" in obj); // true (Object prototype has 'toString' method)

// Best Practice: Use in to check for properties, including inherited ones
console.log("hasOwnProperty" in obj); // true

// 4. Array.isArray() Method
// Array.isArray() is a method that determines whether a value is an array.

console.log(Array.isArray(arr)); // true
console.log(Array.isArray(obj)); // false

// Best Practice: Use Array.isArray() to reliably check if a value is an array
console.log(Array.isArray([1, 2, 3])); // true
console.log(Array.isArray({})); // false

// Summary:
// - Use typeof to check for primitive types and functions.
// - Use instanceof to check if an object is an instance of a specific class.
// - Use in to check if a property exists in an object or its prototype chain.
// - Use Array.isArray() to check if a value is an array.

Interview Questions

1. What is the difference between == and === in JavaScript?

Answer:

  • == compares values for equality, performing type conversion if necessary.
  • === compares values and types for equality without performing type conversion.
console.log(5 == '5');  // true
console.log(5 === '5'); // false
2. How do you increment a variable in JavaScript?

Answer:

You can increment a variable using the ++ operator.

let a = 5;
a++;
console.log(a); // 6
3. Explain the purpose of the typeof operator.

Answer:

typeof is used to determine the data type of a variable or expression.

console.log(typeof 42);         // "number"
console.log(typeof 'Hello');    // "string"
console.log(typeof true);       // "boolean"
4. How does the ternary operator work in JavaScript?

Answer:

The ternary operator is a shorthand for the if-else statement. It takes three operands: a condition, a value if the condition is true, and a value if the condition is false.

let age = 18;
let canVote = (age >= 18) ? 'Yes' : 'No';
console.log(canVote); // "Yes"
5. What is the result of 5 + '5' in JavaScript?

Answer:

The result is '55'. When a number and a string are added, the number is converted to a string, and concatenation occurs.

console.log(5 + '5'); // "55"
6. Describe the difference between null and undefined.

Answer:

  • null is an assigned value indicating the absence of any object value.
  • undefined means a variable has been declared but not yet assigned a value.
let a;
console.log(a); // undefined
let b = null;
console.log(b); // null
7. What does the && operator do in JavaScript?

Answer:

The && operator (Logical AND) returns the first falsy operand or the last operand if all are truthy

console.log(true && false);  // false
console.log(1 && 0);         // 0
console.log(1 && 2);         // 2
8. What is the purpose of the instanceof operator?

Answer:

instanceof checks whether an object is an instance of a specific constructor or class.

let date = new Date();
console.log(date instanceof Date); // true
9. How do you perform bitwise operations in JavaScript?

Answer:

Bitwise operations manipulate individual bits of data. Common operators include & (AND), | (OR), ^ (XOR), ~ (NOT), << (Left Shift), >> (Right Shift), and >>> (Zero-fill Right Shift).

let a = 5; // 0101 in binary
let b = 3; // 0011 in binary
console.log(a & b); // 1 (0001 in binary)
10. Explain the difference between ++a and a++.

Answer:

  • ++a (prefix increment) increments the variable a and returns the new value.
  • a++ (postfix increment) increments the variable a but returns the old value.
let a = 5;
console.log(++a); // 6
console.log(a++); // 6
console.log(a);   // 7
11. What is the result of '5' - 2 in JavaScript?

Answer:

The result is 3. JavaScript converts the string '5' to a number and performs the subtraction.

console.log('5' - 2); // 3
12. How do you use the modulo operator in JavaScript?

Answer:

The modulo operator (%) returns the remainder of the division of two numbers.

console.log(10 % 3); // 1
console.log(15 % 4); // 3
13. Explain the difference between a | b and a || b.

Answer:

  • a | b is a bitwise OR operation that operates on the individual bits of the operands.
  • a || b is a logical OR operation that returns the first truthy operand or the last operand if all are falsy.
14. How does the += operator work in JavaScript?

Answer:

The += operator adds the value on the right to the variable on the left and assigns the result to the variable.

let a = 5;
a += 3;
console.log(a); // 8
15. What is the output of typeof NaN?

Answer:

The output is "number". In JavaScript, NaN (Not-a-Number) is considered a number type.

console.log(typeof NaN); // "number"
16. How can you concatenate strings in JavaScript?

Answer:

Strings can be concatenated using the + operator or the += operator.

let str1 = 'Hello';
let str2 = 'World';
let result = str1 + ' ' + str2;
console.log(result); // "Hello World"
17. What does the ! operator do in JavaScript?

Answer:

The ! operator (Logical NOT) inverts the boolean value of its operand.

let a = true;
console.log(!a); // false

let b = 0;
console.log(!b); // true
18. How does the << operator work?

Answer:

The << operator (Left Shift) shifts the bits of its operand to the left by the specified number of positions, filling the rightmost bits with zeros.

let a = 5; // 0101 in binary
let result = a << 1; // 1010 in binary, which is 10
console.log(result); // 10
19. Explain the result of '5' * '2' in JavaScript.

Answer:

The result is 10. JavaScript converts the strings '5' and '2' to numbers and performs multiplication.

console.log('5' * '2'); // 10
20. How do you check if a variable is an array in JavaScript?

Answer:

You can check if a variable is an array using the Array.isArray method or the instanceof operator.

let arr = [1, 2, 3];
console.log(Array.isArray(arr)); // true
console.log(arr instanceof Array); // true

Practice Exercises

Arithmetic Operators

  1. Complex Addition: Write a function complexAdd(x, y) that takes two numbers, x and y, and returns their sum plus the product of x and y. For example, complexAdd(2, 3) should return 11 (2 + 3 + 2 * 3).
  2. Nested Subtraction: Write a function nestedSubtract(a, b, c) that subtracts b from a, then subtracts c from the result. For example, nestedSubtract(10, 3, 2) should return 5 ((10 – 3) – 2).
  3. Multiplication with Rounding: Write a function multiplyAndRound(a, b) that multiplies a and b, then rounds the result to the nearest integer.
  4. Division with Precision: Write a function divideWithPrecision(a, b) that divides a by b and returns the result rounded to 2 decimal places.
  5. Modulus and Absolute: Write a function modulusAndAbsolute(a, b) that returns the absolute value of the modulus of a divided by b. For example, modulusAndAbsolute(10, 3) should return 1.

Comparison Operators

  1. String Equality and Case Insensitivity: Write a function isStringEqualIgnoreCase(str1, str2) that returns true if str1 and str2 are equal ignoring case, otherwise false.
  2. Strict Equality with Type Check: Write a function strictEqualAndTypeCheck(a, b) that returns an object with two properties: isEqual (true if a and b are strictly equal) and typeMatch (true if a and b are of the same type).
  3. Comparison Chain: Write a function isInRange(value, min, max) that returns true if value is greater than or equal to min and less than or equal to max, otherwise false.
  4. Equality of Arrays: Write a function areArraysEqual(arr1, arr2) that returns true if two arrays arr1 and arr2 have the same elements in the same order.
  5. Object Property Comparison: Write a function compareObjectProperties(obj1, obj2, prop) that compares the values of property prop in obj1 and obj2 and returns true if they are equal, otherwise false.

Logical Operators

  1. Complex AND Operation: Write a function complexAnd(a, b, c) that returns true if a is true and both b and c are false, otherwise false.
  2. OR with Array Check: Write a function orWithArrayCheck(arr, value) that returns true if value is found in arr or arr is empty, otherwise false.
  3. XOR Operation: Write a function xorOperation(a, b) that returns true if exactly one of a or b is true, otherwise false.

Assignment Operators

  1. Compound Assignment: Write a function compoundAssign(x, y, z) that performs x += y * z and returns the result.
  2. Chained Assignments: Write a function chainedAssignments(a, b, c) that assigns a to b, b to c, and returns c.
  3. Ternary Assignment: Write a function ternaryAssign(value) that returns value if it is truthy, otherwise returns "default".

Unary Operators

  1. Unary Plus with String to Number Conversion: Write a function convertToNumber(str) that converts a string str representing a number to a number using the unary plus operator and handles non-numeric strings gracefully.
  2. Unary Minus with Object Conversion: Write a function negateObjectValue(obj) that takes an object with a value property and returns an object with the negated value using the unary minus operator.
  3. Increment and Decrement with Object: Write a function incrementDecrementObject(obj) that increments the count property of an object by 1 and decrements the count property of another object by 1, and returns both objects.
  4. Postfix vs Prefix Increment: Write a function postfixVsPrefix(value) that demonstrates the difference between postfix and prefix increment operators by returning the result of both on a given value.