cover-img

Javascript: Operators

A Comprehensive Guide

11 March, 2023

6

6

1

Contributors

Introduction

JavaScript operators are symbols or keywords that perform operations on one or more values. Operators are used to manipulate data, compare values, and control program flow. JavaScript has several types of operators, including arithmetic operators, comparison operators, logical operators, assignment operators, and more. Understanding how to use operators is crucial for writing effective JavaScript code. In the following sections, we will explore each type of operator in more detail and provide examples of how they are used in JavaScript.

Arithmetic operators

Arithmetic operators in JavaScript are used to perform mathematical operations on numerical values. Here are the most commonly used arithmetic operators with examples:

Arithmetic operator types

  • Addition +: Used to add two or more numbers. For example
let x = 2;
let y = 3;
let z = x + y; // z is now 5
  • Subtraction -: Used to subtract one number from another. For example
let x = 5;
let y = 3;
let z = x - y; // z is now 2
  • Multiplication *: Used to multiply two or more numbers. For example
let x = 5;
let y = 3;
let z = x - y; // z is now 6
  • Division /: Used to divide one number by another. For example
let x = 6;
let y = 3;
let z = x / y; // z is now 2
  • Modulus %: Used to return the remainder of a division operation. For example
let x = 7;
let y = 3;
let z = x % y; // z is now 1 because 3 goes into 7 twice with a remainder of 1
  • Exponentiation **: Used to raise a number to a power. For example
let x = 2;
let y = 3;
let z = x ** y; // z is now 8 because 2 to the power of 3 equals 8

Order of operations

Arithmetic operators follow the order of operations, also known as precedence. The order of operations determines the sequence in which arithmetic operations are performed. The order of operations for arithmetic operators is:

  • Parentheses (): Operations inside parentheses are performed first.
  • Exponentiation **: Exponentiation operations are performed next.
  • Multiplication * and Division /: Multiplication and division operations are performed next, in left-to-right order.
  • Addition + and Subtraction -: Addition and subtraction operations are performed last, in left-to-right order.

It is important to remember the order of operations when writing complex mathematical expressions in JavaScript. Parentheses can be used to group operations together to ensure that they are performed in the correct order. For example, the expression (2 + 3) * 4 equals 20, because the addition operation is performed first inside the parentheses before the multiplication operation.

If the same operator appears multiple times in an expression, the order of operations determines the order in which the operations are performed. For example, the expression 2 + 3 * 4 equals 14, because multiplication takes precedence over addition.

More to mind

a few more things to keep in mind when working with arithmetic operators in JavaScript:

  • Division by zero: Division by zero results in the special value Infinity or -Infinity, depending on the signs of the operands. For example, 5 / 0 equals Infinity, while -5 / 0 equals -Infinity. However, dividing zero by zero results in the special value NaN (Not a Number).
  • Implicit type coercion: When using arithmetic operators with operands of different types, JavaScript will attempt to convert the operands to a common type before performing the operation. For example, if you add a number and a string, JavaScript will convert the string to a number before performing the addition operation. This can sometimes lead to unexpected results, so it's important to understand how JavaScript handles implicit type coercion.
  • Order of evaluation: When an expression contains multiple arithmetic operators, the order of evaluation can affect the result. For example, in the expression 4 + 5 * 3, the multiplication operation is performed first because it has higher precedence than addition. However, you can use parentheses to control the order of evaluation, as in (4 + 5) * 3.

By understanding these concepts, you can avoid common pitfalls and write more robust and predictable code with arithmetic operators in JavaScript.

Comparison operators

Comparison operators are used to compare two values and return a Boolean value (true or false) based on the comparison. JavaScript has several types of comparison operators, including equal to, not equal to, greater than, less than, greater than or equal to, and less than or equal to. Comparison operators are commonly used in conditional statements and loops to control program flow based on the values of variables.

In JavaScript, comparison operators work with a wide range of data types, including numbers, strings, and booleans. When comparing values of different types, JavaScript will attempt to convert one or both operands to a common type before making the comparison. This process is known as type coercion, and it can sometimes lead to unexpected results.

Comparison operator types

Here are the different types of comparison operators in JavaScript and how they work:

  • Equal to ==: The equal to operator compares two values and returns true if they are equal, or false otherwise. When comparing values of different types, JavaScript will attempt to convert one or both operands to a common type before making the comparison. For example, 5 == "5" would return true, because JavaScript coerces the string "5" to a number before making the comparison.
  • Not equal to !=: The not equal to operator compares two values and returns true if they are not equal, or false otherwise. Like the equal to operator, JavaScript will attempt to convert operands of different types before making the comparison.
  • Strict equal to ===: The strict equal to operator compares two values and returns true if they are equal in both value and type, or false otherwise. This operator does not perform type coercion, so 5 === "5" would return false.
  • Strict not equal to !==: The strict not equal to operator compares two values and returns true if they are not equal in either value or type, or false otherwise. Like the strict equal to operator, this operator does not perform type coercion.
  • Greater than >: The greater than operator compares two values and returns true if the first value is greater than the second value, or false otherwise.
  • Less than <: The less than operator compares two values and returns true if the first value is less than the second value, or false otherwise.
  • Greater than or equal to >=: The greater than or equal to operator compares two values and returns true if the first value is greater than or equal to the second value, or false otherwise.
  • Less than or equal to <=: The less than or equal to operator compares two values and returns true if the first value is less than or equal to the second value, or false otherwise.

By understanding how each comparison operator works, you can write more robust and effective code that makes use of conditional statements and loops to control program flow based on the values of variables.

Pitfalls

There are a few pitfalls to keep in mind when working with comparison operators in JavaScript. Here are some of the most common ones:

  • Type coercion: As mentioned earlier, JavaScript will attempt to convert operands of different types before making the comparison. This can sometimes lead to unexpected results, so it's important to be aware of how type coercion works in JavaScript. For example, the expression "" == false would return true, because an empty string is considered falsy in JavaScript and will be coerced to the boolean value false.
  • NaN: NaN (Not a Number) is a special value in JavaScript that represents an undefined or unrepresentable value. When using comparison operators, it's important to keep in mind that NaN is not equal to any other value, including NaN itself. For example, the expression NaN == NaN would return false.
  • Object comparison: When comparing objects in JavaScript, the comparison operator checks whether the objects are the same object in memory, rather than comparing their contents. This means that two objects with the same properties and values will not be considered equal unless they are the same object. To compare objects based on their contents, you will need to write custom comparison functions.
  • Floating point precision: JavaScript uses floating point numbers to represent decimal values, which can sometimes lead to rounding errors when performing comparisons. To avoid this issue, it's recommended to use the toFixed() method to round numbers to a specified number of decimal places before making comparisons.

By keeping these pitfalls in mind and writing code that explicitly handles these cases, you can avoid common issues when working with comparison operators in JavaScript.

Best practices

Here are some best practices to keep in mind when working with comparison operators in JavaScript:

  • Use strict equality === whenever possible: The strict equality operator compares both the value and the type of two operands. It's generally safer to use this operator instead of the loose equality operator == to avoid unexpected type coercion.
  • Be aware of operator precedence: Like arithmetic operators, comparison operators have a specific order of precedence that determines the order in which they are evaluated. It's important to be aware of this order and use parentheses to group expressions when necessary.
  • Use descriptive variable names: When writing conditional statements, it's important to use descriptive variable names that make it clear what values are being compared. This can help avoid confusion and make your code easier to read and maintain.
  • Avoid comparing against undefined: When checking if a variable has a value, it's generally safer to use typeof to check whether the variable is defined, rather than comparing it directly against undefined. This can help avoid issues with variable hoisting and ensure that your code behaves as expected.
  • Use comparison functions for complex objects: When comparing complex objects or arrays, it's often necessary to write custom comparison functions that compare based on specific properties or values. This can help avoid issues with object comparison and ensure that your code is more maintainable. For example:

Let's say you have an array of objects that represent employees, and you want to sort them by their age. Here's an example of how you might write a custom comparison function to achieve this:

const employees = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 20 },
{ name: 'Dave', age: 35 },
];

function compareByAge(a, b) {
if (a.age < b.age) {
return -1;
} else if (a.age > b.age) {
return 1;
} else {
return 0;
}
}

employees.sort(compareByAge);
console.log(employees); // [{ name: 'Charlie', age: 20 }, { name: 'Alice', age: 25 }, { name: 'Bob', age: 30 }, { name: 'Dave', age: 35 }]

In this example, we define a custom function compareByAge that takes two arguments a and b, which represent two employees. The function compares the age property of each employee and returns -1, 1, or 0 depending on whether the first employee is younger, older, or the same age as the second employee.

We then call the sort method on the employees array and pass our custom comparison function as an argument. The sort method uses this function to determine the order in which the employees should be sorted, based on their age.

By using a custom comparison function like this, we can sort the employees array based on any property or combination of properties, rather than just using the built-in comparison operators which only work for simple values like numbers and strings.

By following these best practices, you can write more robust and effective code that makes use of comparison operators in JavaScript.

Assignment operators

An assignment operator is a type of operator that assigns a value to a variable. It is used to modify the value of a variable by assigning a new value to it. The most commonly used assignment operator is the equals sign (=), which is used to assign a value to a variable.

However, there are other assignment operators in JavaScript that provide a shorthand way of performing arithmetic operations and assigning the result back to the same variable. These include the addition assignment operator (+=), subtraction assignment operator (-=), multiplication assignment operator (*=), division assignment operator (/=), and modulus assignment operator (%=).

Assignment operators are commonly used in JavaScript to simplify code and improve readability. They can also be used to increment or decrement a variable's value, and to perform other types of arithmetic operations in a single line of code.

It is important to note that assignment operators follow the same rules of operator precedence as other operators in JavaScript. This means that they are executed from left to right and can be combined with other operators to create complex expressions. Understanding how to use assignment operators effectively is an important part of becoming proficient in JavaScript programming.

Common assignment operators

  • The equals sign = operator is used to assign a value to a variable:
let x = 5; // assigns the value 5 to the variable x
  • The addition assignment operator += adds a value to a variable and assigns the result back to the same variable:
let y = 10;
y += 5; // equivalent to y = y + 5, assigns the value 15 to y
  • The subtraction assignment operator -= subtracts a value from a variable and assigns the result back to the same variable:
let z = 20;
z -= 10; // equivalent to z = z - 10, assigns the value 10 to z
  • The multiplication assignment operator *= multiplies a variable by a value and assigns the result back to the same variable:
let a = 5;
a *= 3; // equivalent to a = a * 3, assigns the value 15 to a
  • The division assignment operator /= divides a variable by a value and assigns the result back to the same variable:
let b = 20;
b /= 4; // equivalent to b = b / 4, assigns the value 5 to b
  • The modulus assignment operator (%=) divides a variable by a value and assigns the remainder back to the same variable:
let c = 17;
c %= 5; // equivalent to c = c % 5, assigns the value 2 to c

In each of these examples, the assignment operator is used to modify the value of a variable. These shorthand versions of the operators can make code more concise and easier to read.

Less common assignment operators

While the most common operators are widely known and used, there are also less common operators that can be very useful in certain situations. Understanding these less common operators can help you write more efficient and effective code.

  • The bitwise AND assignment operator &= performs a bitwise AND operation on a variable and a value, and assigns the result back to the same variable:
let x = 5; // binary 0101
x &= 3; // binary 0011, equivalent to x = x & 3, assigns the value 1 to x
  • The bitwise OR assignment operator |= performs a bitwise OR operation on a variable and a value, and assigns the result back to the same variable:
let y = 10; // binary 1010
y |= 6; // binary 1110, equivalent to y = y | 6, assigns the value 14 to y
  • The bitwise XOR assignment operator ^= performs a bitwise XOR operation on a variable and a value, and assigns the result back to the same variable:
let z = 15; // binary 1111
z ^= 9; // binary 1000, equivalent to z = z ^ 9, assigns the value 8 to z
  • The left shift assignment operator <<= shifts the bits of a variable to the left by a specified number of positions, and assigns the result back to the same variable:
let a = 7; // binary 0111
a <<= 2; // binary 011100, equivalent to a = a << 2, assigns the value 28 to a
  • The right shift assignment operator >>= shifts the bits of a variable to the right by a specified number of positions, and assigns the result back to the same variable:
let b = 32; // binary 100000
b >>= 2; // binary 001000, equivalent to b = b >> 2, assigns the value 8 to b
  • The zero-fill right shift assignment operator >>>= shifts the bits of a variable to the right by a specified number of positions, filling the leftmost bits with zeroes, and assigns the result back to the same variable:
let c = -16; // binary 11111111111111111111111111110000
c >>>= 2; // binary 00111111111111111111111111111100, equivalent to c = c >>> 2, assigns the value 1073741812 to c

These operators are less commonly used in everyday programming, but they can be useful in certain situations, particularly when working with bitwise operations.

Pitfalls

While assignment operators can be useful and save time in coding, there are some pitfalls to watch out for. Here are a few potential pitfalls to keep in mind when using assignment operators:

  • Overwriting data: Assignment operators can overwrite data in a variable, which can lead to unexpected results. For example:
let x = 5;
x += "2"; // x now contains the string "52" instead of the expected number 7
  • Implicit type conversion: Some assignment operators can cause implicit type conversion, which can lead to unexpected results. For example:
let y = 5;
y /= "2"; // y now contains the number 2.5 instead of the expected number 2
  • Order of operations: When using multiple assignment operators in the same statement, the order of operations can be important. For example:
let z = 5;
z += 2 * 3; // z now contains the number 11 instead of the expected number 11

In this case, the multiplication operation is performed before the addition operation, so the result is not what you might expect.

  • Confusing with comparison operators: Some of the assignment operators (such as = and +=) can be easily confused with comparison operators (such as == and ===), which can lead to errors. For example:
let a = 5;
if (a = 2) { // This will always evaluate to true, because the assignment operator returns the assigned value (2)
// Code here will always execute, even though a is not equal to 2
}

To avoid these pitfalls, it is important to be careful when using assignment operators and to double-check your code for potential issues. Additionally, using explicit type conversion (such as Number() or parseInt()) can help avoid implicit type conversion issues.

Best practices

  • Use explicit type conversion: To avoid unexpected results due to implicit type conversion, use explicit type conversion functions like Number(), parseInt(), parseFloat(), and String().
  • Use parentheses for clarity: To avoid issues with order of operations, use parentheses to group operations and make your code easier to read. For example:
let x = 5;
x += (2 * 3); // Explicitly grouping the multiplication operation with parentheses makes it clear that it will be performed first
  • Avoid using unnecessary assignment operators: While shorthand assignment operators can be useful, don't use them unnecessarily. Sometimes it's more clear to use the full assignment operator for clarity. For example:
let y = "Hello";
y += " World"; // This is a good use of the shorthand operator
let z = 5;
z = z + 1; // Using the full assignment operator is more clear in this case
  • Avoid using assignment operators in conditional statements: Using an assignment operator (=) instead of a comparison operator (== or ===) in a conditional statement can lead to unintended behaviour. Always use a comparison operator in conditional statements to avoid confusion.

By following these best practices, you can write code that is more readable, reliable, and less prone to errors.

Logical operators

Logical operators are used to combine or evaluate Boolean expressions. Logical operators can be used to check if one or both expressions are true or false, and they can be used to create more complex Boolean expressions. The three logical operators in JavaScript are AND (&&), OR (||), and NOT (!). Understanding how to use these logical operators can be very useful in writing conditional statements and creating more advanced Boolean expressions in your JavaScript code.

Examples

  • AND (&&): The AND operator returns true if both expressions are true, and false otherwise. For example:
let x = 5;
let y = 10;
if (x < 10 && y > 5) {
// Code here will execute because both expressions are true
}
  • OR (||): The OR operator returns true if either expression is true, and false otherwise. For example:
let a = 5;
let b = 10;
if (a < 4 || b > 5) {
// Code here will execute because at least one expression is true
}
  • NOT (!): The NOT operator returns the opposite Boolean value of the expression it is applied to. For example:
let z = true;
if (!z) {
// Code here will not execute because the expression is false (z is true)
}

Logical operators can also be combined to create more complex Boolean expressions. For example:

let isSunny = true;
let temperature = 75;
let hasBeachGear = false;

if ((isSunny && temperature >= 70) || hasBeachGear) {
// Code here will execute if it is sunny and at least 70 degrees OR if hasBeachGear is true
}

In this example, we are using parentheses to group the expressions in a specific order. The AND operator is evaluated first, followed by the OR operator. By understanding how to combine logical operators in different ways, you can create more sophisticated and powerful Boolean expressions in your JavaScript code.

Pitfalls

  • Short-circuit evaluation: JavaScript uses short-circuit evaluation for logical operators. This means that if the first expression in an AND (&&) operator is false, the second expression will not be evaluated. Similarly, if the first expression in an OR (||) operator is true, the second expression will not be evaluated. While this can be useful for improving performance, it can also lead to unexpected behaviour if you're not aware of it.
let x = 0;
if (x > 5 && x / 0 > 5) {
// This code will not execute because the first expression (x > 5) is false, so the second expression is not evaluated
}
  • Mixing types: When using logical operators, make sure that the expressions being compared are of the same type. Mixing types can lead to unexpected results due to implicit type conversion.
let y = "hello";
if (y && 0) {
// This code will not execute because the expression (y && 0) evaluates to false
}

In this example, the y variable is a string, and the 0 value is a number. When using the AND operator to compare them, JavaScript will convert the string to a Boolean value (which will be true for any non-empty string) and the number to a Boolean value (which will be false for the number 0). The final result will be false, even though it may not be what you intended.

  • Overcomplicating expressions: While it can be tempting to create complex expressions using multiple logical operators, this can make your code harder to read and debug. Try to keep your expressions simple and straightforward whenever possible.

Best practices

  • Use parentheses to group expressions: When combining multiple logical operators, use parentheses to group expressions together and ensure that they are evaluated in the correct order. This can make your code more readable and prevent unexpected behaviour.
if ((x > 5 && y < 10) || z === "hello") {
// Code here
}
  • Use descriptive variable names: When using logical operators in your code, use descriptive variable names to make the code easier to understand. For example, instead of using x and y as variable names, use names that describe the values being compared, such as age and temperature.
if (age >= 18 && temperature > 70) {
// Code here
}
  • Avoid unnecessary negation: While the NOT (!) operator can be useful for negating a Boolean expression, using it excessively can make your code harder to read and understand. Instead of negating an expression, try to express it in a positive way whenever possible.
// Instead of using negation like this:
if (!(age < 18)) {
// Code here
}

// Use positive expressions like this:
if (age >= 18) {
// Code here
}

Comma operator

The comma operator is a rarely used operator that allows you to combine two or more expressions into a single expression. It evaluates each expression in turn, from left to right, and returns the value of the last expression. While the comma operator can be useful in certain situations, such as when initializing multiple variables in a for loop or when passing multiple arguments to a function, it can also make your code harder to read and understand. In general, it is best to use the comma operator sparingly and only when it improves the clarity and efficiency of your code.

Example

Here's an example of using the comma operator to initialise multiple variables in a for loop:

for (var i = 0, j = 10; i < j; i++, j--) {
console.log("i = " + i + ", j = " + j);
}

In this example, the for loop initialises two variables, i and j, using the comma operator. The first expression var i = 0 initialises the variable i to zero, and the second expression j = 10 initialises the variable j to 10. The loop condition i < j is evaluated at the beginning of each iteration of the loop, and the loop increment i++, j-- is evaluated at the end of each iteration. The loop prints the value of i and j at each iteration, decrementing j and incrementing i until i is no longer less than j.

Pitfalls

The comma operator in JavaScript can be confusing and can lead to unexpected behaviour if not used carefully. Here are some pitfalls to be aware of when using the comma operator:

  • Order of evaluation: The comma operator evaluates expressions from left to right, which can be a source of confusion if you are not expecting it. For example, in the expression a = b, c = d, b is assigned to a first, and then d is assigned to c. If you are not careful, this can lead to bugs in your code.
  • Confusing with function arguments: Using the comma operator in function arguments can be confusing, especially when combined with other operators. For example, in the expression foo(a, b, c + d, e * f), it is not immediately clear which arguments are being combined with the comma operator and which are not.
  • Overuse: The comma operator can make code hard to read and understand, especially when used excessively. While it can be useful in certain situations, such as initializing multiple variables in a for loop, it should be used sparingly and only when it improves the clarity and efficiency of your code.

To avoid these pitfalls, it's important to use the comma operator judiciously and to be clear and explicit in your use of parentheses and other grouping operators to ensure that expressions are evaluated in the correct order.

Best practices

Here are some best practices to follow when using the comma operator:

  • Use it sparingly: The comma operator can make code harder to read and understand, so it's best to use it only when it improves the clarity and efficiency of your code.
  • Be explicit with parentheses: To ensure that expressions are evaluated in the correct order, use parentheses and other grouping operators to make your code clear and explicit. For example, in the expression (a + b), (c + d), the parentheses ensure that a + b is evaluated before c + d.
  • Use it in simple expressions: The comma operator is most useful in simple expressions, such as initializing multiple variables in a for loop or combining simple expressions in a single statement.
  • Avoid using it in function arguments: Using the comma operator in function arguments can be confusing and hard to read. If you need to pass multiple arguments to a function, use an array or object instead.
  • Use comments to explain your code: If you use the comma operator in a way that might be confusing or unclear to others, use comments to explain your code and make it easier to understand.

Unary operators

Unary operators operate on a single operand and can perform a variety of operations, such as negating a value, converting a value to a different type, or incrementing or decrementing a value. There are several unary operators in JavaScript, each with its own set of rules and best practices. Understanding how to use unary operators effectively can help you write cleaner, more efficient code in JavaScript.

Plus operator

The unary plus operator + can be used to convert a value to a number. When applied to a non-numeric value, the unary plus operator attempts to convert the value to a numeric type.

Here's an example:

let x = "42";
let y = +"42";

console.log(x); // "42"
console.log(y); // 42

In this example, the x variable is assigned the string value "42", while the y variable is assigned the numeric value 42. The + operator is used to convert the string "42" to a numeric value.

If the value cannot be converted to a number, the result of the operation is NaN (not a number). For example:

let z = +"hello";

console.log(z); // NaN

It's important to note that the unary plus operator has a higher precedence than the addition operator (+). This means that if you have an expression that includes both the unary plus operator and the addition operator, the unary plus operator is applied first. For example:

let a = 5;
let b = "10";

console.log(a + +b); // 15

In this example, the expression +b is evaluated first, converting the string "10" to the numeric value 10. The result of the expression is then a + 10, which is 15.

Overall, the unary plus operator can be a useful tool for converting values to numbers in JavaScript. However, it should be used with caution, as unexpected results can occur if the value cannot be converted to a number.

Negation operator

The unary negation operator - can be used to negate a numeric value. When applied to a numeric value, the unary negation operator returns the negative of that value.

Here's an example:

let x = 5;
let y = -x;

console.log(x); // 5
console.log(y); // -5

In this example, the x variable is assigned the value 5, and the y variable is assigned the negation of x, which is -5.

The unary negation operator can also be used to convert a value to a negative number. For example:

let z = -"10";

console.log(z); // -10

In this example, the string "10" is converted to the number 10, and the unary negation operator is used to negate that value, resulting in -10.

If the value cannot be converted to a number, the result of the operation is NaN (not a number). For example:

let w = -"hello";

console.log(w); // NaN

As with the unary plus operator, it's important to note that the unary negation operator has a higher precedence than the subtraction operator (-). This means that if you have an expression that includes both the unary negation operator and the subtraction operator, the unary negation operator is applied first. For example:

let a = 5;
let b = "10";

console.log(a - -b); // 15

In this example, the expression -b is evaluated first, converting the string "10" to the numeric value 10 and negating it, resulting in -10. The result of the expression is then a - -10, which is 15.

Overall, the unary negation operator can be a useful tool for negating or converting values in JavaScript. However, it should be used with caution, as unexpected results can occur if the value cannot be converted to a number.

Logical NOT operator

The unary logical NOT operator (!) can be used to invert the "truthiness" of a value. When applied to a value, the unary logical NOT operator returns false if the value is truthy and true if the value is "falsy".

Here's an example:

let x = 5;
let y = !x;

console.log(x); // 5
console.log(y); // false

In this example, the x variable is assigned the value 5, and the y variable is assigned the result of applying the unary logical NOT operator to x, which is false because x is a truthy value.

The unary logical NOT operator can be used with any value type in JavaScript. For example:

console.log(!"hello"); // false
console.log(!""); // true
console.log(!0); // true
console.log(!NaN); // true
console.log(!null); // true
console.log(!undefined); // true

In each of these examples, the unary logical NOT operator is applied to a different value, resulting in either true or false depending on the truthiness of the value.

It's important to note that the unary logical NOT operator has a higher precedence than other operators, including the comparison operators (==, !=, ===, !==, <, >, <=, and >=). This means that if you have an expression that includes both the unary logical NOT operator and a comparison operator, the unary logical NOT operator is applied first. For example:

let a = 5;
let b = 10;

console.log(!(a < b)); // false

Here, the expression a < b is evaluated first, resulting in true. The unary logical NOT operator is then applied to the result, resulting in false.

Overall, the unary logical NOT operator can be a useful tool for inverting the truthiness of values in JavaScript. However, it should be used with caution, as unexpected results can occur if the value is not properly evaluated for truthiness.

Bitwise NOT operator

The Bitwise NOT operator (~) is used to perform bitwise negation on an integer. When applied to an integer value, the Bitwise NOT operator performs a bitwise NOT operation on the binary representation of the integer, effectively flipping all of the bits.

Here's an example:

let x = 5;
let y = ~x;

console.log(x); // 5
console.log(y); // -6

Here, the x variable is assigned the value 5, and the y variable is assigned the result of applying the Bitwise NOT operator to x, which is -6.

This is because the binary representation of 5 is 00000000000000000000000000000101, and applying the Bitwise NOT operator to this value results in 11111111111111111111111111111010. This binary value, when interpreted as an integer in two's complement form, represents -6.

The Bitwise NOT operator can be used with any integer value in JavaScript. For example:

console.log(~0); // -1
console.log(~1); // -2
console.log(~2); // -3
console.log(~3); // -4

In each of these examples, the Bitwise NOT operator is applied to a different integer value, resulting in a different integer value as the output.

The Bitwise NOT operator has a higher precedence than other operators, except for the parentheses operator. This means that if you have an expression that includes both the Bitwise NOT operator and other operators, the Bitwise NOT operator is applied first. For example:

let a = 5;
let b = 10;

console.log(~(a + b)); // -16

Here, the expression a + b is evaluated first, resulting in 15. The Bitwise NOT operator is then applied to the result, resulting in -16.

Overall, the Bitwise NOT operator can be a useful tool for performing bitwise operations on integer values in JavaScript. However, it should be used with caution, as unexpected results can occur if the value is not properly interpreted as an integer in two's complement form.

typeof operator

The typeof operator is used to determine the data type of a given value. It returns a string indicating the data type of the operand.

Here's an example:

let x = 5;
let y = "hello";
let z = true;

console.log(typeof x); // "number"
console.log(typeof y); // "string"
console.log(typeof z); // "boolean"

In this example, the typeof operator is applied to three different values: 5, "hello", and true. The output of each typeof operation is a string indicating the data type of the operand.

The typeof operator can be used with any value in JavaScript, including variables, expressions, and function calls. For example:

let a;
let b = null;
let c = [1, 2, 3];

console.log(typeof a); // "undefined"
console.log(typeof b); // "object"
console.log(typeof c); // "object"
console.log(typeof console.log); // "function"

In each of these examples, the typeof operator is applied to a different value, resulting in a different string as the output.

It's important to note that the typeof operator has some quirks and limitations. For example, it returns "object" for null values and some objects, such as arrays and functions. Additionally, it cannot distinguish between different kinds of objects or primitives with the same data type. For example:

console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(typeof new Date()); // "object"
console.log(typeof "hello"); // "string"
console.log(typeof new String("hello")); // "object"

In each of these examples, the typeof operator returns "object" for various kinds of objects, including empty objects, arrays, and Date objects. It also returns "string" for both string literals and String objects.

Despite these quirks and limitations, the typeof operator can be a useful tool for checking the data type of a value in JavaScript. It is commonly used in conditional statements and error handling to ensure that a value is of the expected type before proceeding with further code execution.

void operator

The void operator is used to evaluate an expression and return undefined. The expression can be any valid JavaScript expression, such as a function call, variable, or literal.

Here's an example:

let result = void console.log("Hello, world!");
console.log(result); // undefined

Here, the void operator is used to evaluate the console.log("Hello, world!") expression and return undefined. The result of the void operation is then assigned to the result variable, which is logged to the console, resulting in the output undefined.

The void operator is often used in conjunction with anchor tags (<a> tags) in HTML to prevent the default behaviour of the browser when the link is clicked. For example:

<a href="javascript:void(0);" onclick="doSomething()">Click me</a>

Here, the href attribute of the <a> tag is set to "javascript:void(0);", which evaluates to undefined. When the link is clicked, the doSomething() function is called, but the default behaviour of following the link is prevented because the href attribute is evaluated to undefined.

It's worth noting that the void operator is not commonly used in day-to-day JavaScript programming, and it has limited practical applications. However, it can be a useful tool in certain situations, such as preventing default browser behaviour when handling user interactions with HTML elements.

Delete operator

The delete operator is used to delete a property from an object or remove an element from an array. The syntax for using the delete operator is:

delete object.property; // removes a property from an object
delete object[index]; // removes an element from an array

Note that the delete operator only removes the reference to the property or element, but it does not delete the property or element from memory. If the property or element is part of an object or array that is still referenced elsewhere, it will not be garbage collected.

It's important to note that the delete operator has some limitations and caveats. For example, it cannot be used to delete variables declared with var, let, or const. It also returns a boolean value indicating whether the deletion was successful or not.

Another important thing to consider is that the delete operator can have unexpected results if used improperly. For example, if you try to delete a property that is part of a built-in object, such as Object.prototype, the operation may fail silently, or worse, delete the property from the prototype of all objects. Similarly, if you try to delete a non-existent property, the operation will succeed, but it will not have any effect.

In general, the delete operator should be used judiciously and only when necessary. It's important to test your code thoroughly to ensure that it behaves as expected and to be aware of the limitations and potential pitfalls of using the delete operator.

Increment operator

The increment operator is used to increase the value of a variable by 1. There are two types of increment operators: the pre-increment operator (++x) and the post-increment operator (x++).

The pre-increment operator (++x) increments the value of the variable before any other operation is performed. For example:

let x = 5;
let y = ++x; // y is 6, x is 6

In this example, the ++x operation increments the value of x to 6 before it is assigned to the y variable.

The post-increment operator (x++) increments the value of the variable after any other operation is performed. For example:

let x = 5;
let y = x++; // y is 5, x is 6

Here, the x++ operation assigns the original value of x (5) to the y variable and then increments the value of x to 6.

It's worth noting that the increment operator can only be used with numeric values. If you try to use it with a non-numeric value, such as a string or boolean, the value will be converted to a number before the operation is performed.

Another thing to keep in mind is that the increment operator can be used in shorthand notation. For example, x += 1 is equivalent to x++, and x -= 1 is equivalent to x--.

Finally, it's important to use the increment operator with caution, as it can sometimes lead to unexpected results or errors if used improperly. For example, if used in a loop without proper termination conditions, it can lead to an infinite loop. As with any operator, it's important to understand how it works and use it appropriately in your code.

Decrement operator

The unary decrement operator subtracts 1 from the variable's current value and then assigns the result back to the same variable. The operator works with both pre-decrement and post-decrement modes.

The syntax for the pre-decrement mode is:

--x

In this mode, the decrement operator is placed before the variable. The value of the variable is first decremented and then the new value is returned.

The syntax for the post-decrement mode is:

x--

In this mode, the decrement operator is placed after the variable. The value of the variable is returned first and then the variable is decremented.

Here are some examples of using the unary decrement operator:

let a = 5;

console.log(--a); // 4 (pre-decrement)
console.log(a); // 4

console.log(a--); // 4 (post-decrement)
console.log(a); // 3

In the first example, the pre-decrement operator is used to decrement the value of a by 1 before logging the new value to the console. In the second example, the post-decrement operator is used to log the current value of a to the console before decrementing it by 1.

Note that the decrement operator can be used with any variable or property that can be coerced into a number. If the operand cannot be coerced into a number, the decrement operator will return NaN.

Pitfalls

While the unary operators in JavaScript can be useful in certain situations, there are some pitfalls that developers should be aware of when using them.

  • Confusing code: Using too many unary operators or using them in complex expressions can make the code hard to read and understand. This can make the code difficult to maintain and debug in the future.
  • Side effects: Some unary operators, such as the increment and decrement operators, can have side effects that can lead to unexpected behaviour in the code. For example, using the post-increment or post-decrement operator in a complex expression can result in different behaviour than using the pre-increment or pre-decrement operator.
  • Type coercion: The unary operators in JavaScript can perform type coercion, which can lead to unexpected results. For example, the unary plus operator can convert a string into a number, but it can also result in NaN if the string cannot be converted.
  • Performance: Using unary operators can sometimes result in slower performance than using other types of operators. This is because the JavaScript engine has to perform type coercion and other operations to execute the operator, which can take more time than simpler operators.

To avoid these pitfalls, developers should use unary operators judiciously and only when they are necessary. It is also a good practice to write clear and readable code, and to test the code thoroughly to ensure that it behaves as expected.

Best practices

  • Use unary operators only when necessary: While unary operators can be useful in some situations, overusing them can make code harder to read and understand. Consider using alternative approaches, such as simple math expressions, when possible.
  • Use parentheses to clarify expressions: When using a unary operator in a complex expression, use parentheses to clarify the order of operations and improve readability. For example, -(a + b) is clearer than -a + b.
  • Avoid using the ++ and -- operators in complex expressions: The increment and decrement operators can have unexpected side effects when used in complex expressions. Consider using the += and -= operators instead, or break complex expressions down into simpler steps.
  • Be aware of type coercion: Some unary operators, such as the unary plus operator, can perform type coercion, which can lead to unexpected results. Be sure to test your code thoroughly to ensure that it behaves as expected.
  • Use descriptive variable names: When using unary operators with variables, use descriptive names that clarify the purpose and function of the variable. This can make code easier to read and understand.

By following these best practices, you can use unary operators effectively and avoid common pitfalls that can lead to hard-to-debug issues in your code.

Spread operator

The spread operator is a syntactic construct in JavaScript introduced in ES6 (ECMAScript 2015) that allows an iterable (e.g. an array or a string) to be expanded into individual elements.

Syntax

The syntax for using the spread operator is the ellipsis ... followed by the name of the iterable object:

const arr = [1, 2, 3];
const copyArr = [...arr];
console.log(copyArr); // [1, 2, 3]

In this example, the spread operator is used to create a copy of the original array arr by expanding its individual elements into a new array copyArr.

The spread operator can also be used to combine multiple arrays or objects into a single array or object:

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combinedArr = [...arr1, ...arr2];
console.log(combinedArr); // [1, 2, 3, 4, 5, 6]

const obj1 = { x: 1, y: 2 };
const obj2 = { z: 3 };
const combinedObj = { ...obj1, ...obj2 };
console.log(combinedObj); // { x: 1, y: 2, z: 3 }

In these examples, the spread operator is used to expand the elements of the original arrays and objects into a new combined array or object.

The spread operator can also be used with functions to pass an array as individual arguments:

function myFunc(x, y, z) {
console.log(x + y + z);
}

const arr = [1, 2, 3];
myFunc(...arr); // logs 6

Here, the spread operator is used to pass the elements of the arr array as individual arguments to the myFunc function.

Overall, the spread operator is a powerful and useful feature in JavaScript that can simplify common programming tasks, such as copying arrays or combining objects

Pitfalls

While the spread operator is a powerful feature in JavaScript, it can also have some potential pitfalls that you should be aware of:

  • Performance considerations: When used excessively or with large arrays, the spread operator can negatively impact performance. This is because it creates new arrays and objects, which can be memory-intensive and time-consuming operations.
  • Reference vs. value: When using the spread operator to create copies of arrays or objects, it's important to understand that it creates shallow copies, which means that only the top-level properties or elements are copied. If the original object or array contains nested objects or arrays, those will still be referenced by both the original and the copied object or array. This can lead to unexpected behaviour and bugs.
  • Type coercion: The spread operator can cause unintended type coercion, especially when used with non-iterable objects. For example, if you try to spread a number or a boolean, it will be coerced into an array with one element. Similarly, if you try to spread an object with non-enumerable properties, those properties will be ignored.
  • Compatibility issues: The spread operator is a relatively new feature in JavaScript and may not be supported by all browsers or environments. To ensure maximum compatibility, you may need to use a transpiler or a polyfill.

To avoid these pitfalls, it's important to use the spread operator judiciously and to test your code thoroughly to ensure that it behaves as expected. Additionally, it's important to be familiar with the limitations and quirks of the spread operator, such as its shallow copy behaviour and potential performance impacts.

Best practices

  • Use it sparingly: The spread operator can be a powerful tool, but it should not be overused. In particular, be careful when using it with large arrays or objects, as it can negatively impact performance.
  • Use it for copying arrays and objects: One of the most common use cases for the spread operator is to create shallow copies of arrays and objects. This can be a handy technique for working with data without modifying the original source.
  • Be aware of shallow copying: Remember that the spread operator creates a shallow copy of an object or array. This means that if the object or array contains nested objects or arrays, those will still be referenced by both the original and the copied object or array. If you need a deep copy, you may need to use a separate utility function or a library.
  • Use it for merging arrays and objects: The spread operator can also be useful for merging multiple arrays or objects into a single array or object.
  • Use it with rest parameters: The spread operator can be used together with the rest parameter syntax to create flexible function signatures that can accept variable numbers of arguments.
  • Consider compatibility: The spread operator is a relatively new feature in JavaScript and may not be supported by all browsers or environments. To ensure maximum compatibility, you may need to use a transpiler or a polyfill.

By following these best practices, you can use the spread operator effectively and avoid common pitfalls.

instanceof

The instanceof operator is a binary operator in JavaScript that checks if an object is an instance of a particular class or constructor function. It returns a boolean value that indicates whether the object is an instance of the specified class.

Syntax

The instanceof operator is used in the following syntax:

object instanceof constructor

Here, object is the object that you want to check, and constructor is the constructor function that represents the class you want to check against.

For example, you can check if an object is an instance of the Array class like this:

const myArray = [1, 2, 3];
console.log(myArray instanceof Array); // output: true

Here, we are checking if myArray is an instance of the Array class using the instanceof operator. Since myArray is an array, which is an instance of the Array class, the operator returns true.

You can also use instanceof to check if an object is an instance of a custom class. For example, suppose you have defined a Person class and you want to check if an object is an instance of that class:

class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}

const john = new Person('John', 30);
console.log(john instanceof Person); // output: true

In this example, we are checking if the john object is an instance of the Person class using the instanceof operator. Since john was created using the Person constructor function, which represents the Person class, the operator returns true.

The instanceof operator can be a useful tool for checking the type of an object in certain situations, but it has some limitations. For example, it only works with constructor functions and does not work with primitive types like numbers or strings. Additionally, it can produce unexpected results if you are working with objects that inherit from multiple classes or if you are using custom class hierarchies.

Pitfalls

The instanceof operator can be a useful tool for checking the type of an object, but it has some limitations and pitfalls that you should be aware of:

  • It only works with constructor functions: The instanceof operator only works with constructor functions and does not work with primitive types like numbers or strings.
  • It checks for type, not identity: The instanceof operator checks whether an object is an instance of a particular class or constructor function. It does not check whether the object is the same object as another object.
  • It can produce unexpected results with custom class hierarchies: If you are working with custom class hierarchies that use inheritance, the instanceof operator can produce unexpected results. For example, if you have a subclass that inherits from a superclass, an object that is an instance of the subclass will also be an instance of the superclass. This can lead to unexpected results if you are not careful.
  • It can produce false positives: In some cases, the instanceof operator can produce false positives. For example, if you have two objects that were created using different versions of the same constructor function, the instanceof operator may return true even though the objects are not actually the same type.
  • It can be less flexible than other type checking methods: The instanceof operator is a specific type checking method and may not be as flexible as other type checking methods. For example, you may need to use other methods like typeof or Object.prototype.toString() to check the types of non-object values or to check for specific object types that do not have constructor functions.

It's important to use instanceof judiciously and to be aware of its potential pitfalls. If you are working with custom class hierarchies or complex object structures, you may need to use other type checking methods to ensure that your code behaves correctly.

Best practices

  • Use instanceof with constructor functions: The instanceof operator is typically used to check whether an object is an instance of a particular constructor function. To use instanceof effectively, make sure that the right-hand side of the operator is a constructor function, not an object or a primitive value.
  • Be aware of the prototype chain: The instanceof operator checks whether an object is an instance of a particular constructor function or one of its ancestors in the prototype chain. This means that if a constructor function has a parent constructor function, objects created by the parent constructor function will also be considered instances of the child constructor function. To avoid unexpected results, be aware of the prototype chain and make sure that you're checking for the right constructor function.
  • Use Object.prototype.toString for built-in objects: While instanceof works well for checking whether an object is an instance of a constructor function, it doesn't work for built-in objects like Array, Date, or RegExp. To check whether an object is an instance of a built-in object, use the Object.prototype.toString method instead.
  • Use Object.getPrototypeOf() to check an object's prototype: If you need to check an object's prototype directly, use the Object.getPrototypeOf() method instead of the instanceof operator. This method returns the prototype of an object, which you can then check against a constructor function or another prototype.

By following these best practices, you can use the instanceof operator effectively and avoid common pitfalls.

In

The in operator is used to check if a specified property exists in an object or if a specified index exists in an array. It returns a boolean value indicating whether the specified property or index exists or not.

Syntax

The syntax for using the in operator is as follows:

propertyNameOrIndex in objectOrArray

Here, propertyNameOrIndex can be a string representing the name of a property in an object or a number representing an index in an array. objectOrArray can be an object or an array.

If the specified property or index exists in the object or array, the in operator returns true. Otherwise, it returns false.

For example, consider the following object:

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

We can use the in operator to check if a property exists in the object as follows:

console.log('name' in person); // true
console.log('gender' in person); // false

In this example, the first console.log statement returns true because the name property exists in the person object. The second console.log statement returns false because the gender property does not exist in the person object.

Similarly, we can use the in operator to check if an index exists in an array as follows:

const numbers = [1, 2, 3, 4, 5];
console.log(2 in numbers); // true
console.log(6 in numbers); // false

In this example, the first console.log statement returns true because the element at index 2 exists in the numbers array. The second console.log statement returns false because there is no element at index 6 in the numbers array.

One thing to note is that the in operator does not distinguish between properties that are inherited from the object's prototype chain and properties that are directly defined on the object itself. If you need to check for the existence of a property only on the object itself (not its prototype chain), you can use the Object.prototype.hasOwnProperty() method instead.

Pitfalls

There are a few pitfalls to be aware of when using the in operator in JavaScript:

  • Prototype chain traversal: The in operator checks for the existence of a property in an object's prototype chain as well as on the object itself. This means that if a property is defined on an object's prototype chain, the in operator will return true even if the property is not defined on the object itself. This can lead to unexpected results if you are not aware of the prototype chain and how it affects property lookup.
  • Array index confusion: When using the in operator with arrays, it's important to remember that the operand on the left side of the in operator is the index number, not the value at that index. This can lead to confusion if you expect the in operator to work like the indexOf() method.
  • Overloading of properties: The in operator only checks for the existence of a property, not its value. This means that if a property is defined on an object with a falsy value (such as null, undefined, 0, false, or ''), the in operator will still return true. This can lead to unexpected behaviour if you are not careful.
  • Performance: The in operator can be slower than other methods for checking the existence of a property or index, especially when used in a loop or with large objects or arrays. In these cases, it may be more efficient to use other methods, such as the hasOwnProperty() method or the indexOf() method.

To avoid these pitfalls, it's important to understand how the in operator works and to use it appropriately. If you are unsure whether the in operator is the best option for your use case, consider using a different method for checking the existence of a property or index.

Best practices

  • Be aware of the prototype chain: The in operator checks for the existence of a property in an object's prototype chain as well as on the object itself. This means that if a property is defined on an object's prototype chain, the in operator will return true even if the property is not defined on the object itself. To avoid unexpected results, it's important to be aware of the prototype chain and to use the hasOwnProperty() method if you only want to check for properties on the object itself.
  • Use the hasOwnProperty() method: If you only want to check for properties on the object itself and not on its prototype chain, use the hasOwnProperty() method instead of the in operator. This method checks whether an object has a property with the specified name and returns true if the property exists on the object itself, not on its prototype chain.
  • Use other methods for arrays: When working with arrays, the in operator can be confusing because it checks for the existence of an index number, not the value at that index. To check whether an array contains a specific value, use the indexOf() method or the includes() method instead of the in operator.
  • Be careful with falsy values: The in operator only checks for the existence of a property, not its value. This means that if a property is defined on an object with a falsy value (such as null, undefined, 0, false, or ''), the in operator will still return true. To avoid unexpected behaviour, be careful when using the in operator with falsy values.

By following these best practices, you can use the in operator effectively and avoid common pitfalls.

Conclusion

Operators are a crucial aspect of programming in JavaScript. They enable developers to perform operations on data, manipulate variables, and control the flow of logic in their code. Operators come in different types and have various uses, including unary, binary, and ternary operators.

Unary operators, for instance, allow you to perform an operation on a single operand. They are used to increment or decrement a value, negate a value, or convert a value to a different type. Some of the common unary operators in JavaScript include the typeof, void, and delete operators.

Binary operators, on the other hand, require two operands to perform an operation. They are used to perform arithmetic operations such as addition, subtraction, multiplication, and division. They are also used to compare values, assign values, and concatenate strings. Some of the common binary operators in JavaScript include the +, -, *, /, =, and == operators.

Ternary operators are a shorthand way of writing an if-else statement. They are used to assign one of two values to a variable, depending on whether a condition is true or false. The syntax for the ternary operator is condition ? valueIfTrue : valueIfFalse.

While operators are a useful tool for developers, it's essential to be aware of the pitfalls associated with them. For example, using the == operator for value comparison can lead to unexpected results due to type coercion. It's also important to follow best practices when using operators, such as using the === operator for strict value comparison and avoiding unnecessary use of the delete operator.

In conclusion, operators are a critical component of JavaScript programming, and understanding their types, uses, and best practices is essential for writing clean, efficient, and maintainable code. By mastering operators, developers can build more robust and reliable applications that meet the needs of their users.

tutorial

javascript

js

6

6

1

tutorial

javascript

js

ozboware
PHP and Javascript app developer

More Articles