Arithmetic and comparison operators

JavaScript comes with a set of operators you'd expect from any modern language. There are four categories: arithmetic, comparison, assignment, and logical.

Arithmetic Operators

Arithmetic operators perform basic computations on their operands (the variables they operate on). In the table below, variable a has a value of 2 before the operation is applied.

Operator Operation Expression Result
+ Add 2 + a 4
- Substract 2 - a 0
* Multiply 3 * a 6
/ Divide 3 / a 1.5
% Modulus - division remainder 7 % a 1
++ Increment - increase by 1 a++ 3
-- Decrement - decrease by 1 a-- 1

String Operators

The + operator is used for adding numeric values, but it can also be used to concatenate (join) two or more strings and return a single string. Here is an example:

var str1 = "Hello";
var str2 = " Vivek";
str1 = str1 + str2;        // => "Hello Vivek"
alert(str1);
Run

The last statement can also be rewritten by using the assignment += operator as follows:

var str1 = "Hello";
var str2 = " Vivek";
str1 += str2;              // => "Hello Vivek"
alert(str1);
Run

Comparison Operators

Comparison operators compare the value of two operands. If the comparison is true, they return true, otherwise false. In the table below the variables are: a = 1 and b = 2.

Operator Operation Expression Result
== Equal to a == b false
!= Not equal to a != b true
<= Less than equal to a <= b true
>= Greater than or equal to a >= b false
< Less than a < b true
> Greater than a > b false




Assignment and boolean operators

Assignment Operators

In an assignment operation the value of a variable is computed from the expression that lies to the right of an assignment operator. That value is assigned to the variable or property that is on the left side of the operator. In the table below the variables have the following values:
a = 1, b = 2, and c = 3.

Operator Operation Result
= a = b + c; a = 5
+= a += b;    // equivalent to a = a + b a = 3
-= a -= b;    // equivalent to a = a – b a = -1
/= a /= b;    // equivalent to a = a / b a = 0.5
%= c %= b;   // equivalent to c = c % b c = 1
*= a *= b;    // equivalent to a = a * b a = 2

Logical or Boolean Operators

Logical or Boolean operators compare Boolean expressions and then return true or false. The && and || ('and' and 'or') operators take two operands. The ! ('not') operator takes a single operand. In the table below the variables have the following values: a = 1 and b = 2.

Operator Operation Expression Result
&& Logical and. Returns true only if both its first and second operands are evaluated to true. a < 3 && b > 5 returns false as b > 5 is false
|| Logical or. Returns true if one of the two operands are evaluated to true, returns false if both are evaluated to true. a < 3 || b > 5 returns true as a < 3 is true
! Logical not. Unary operator that simply inverts the Boolean value of its operand. !(b>5) returns true




Special numeric values: Infinity, NaN

In most languages, dividing a number by 0 throws an error and stops program execution. JavaScript however, returns a special infinity value, printed as Infinity, when the result of a numeric operation is larger than the largest representable number

Similarly, it returns a negative infinity value, printed as -Infinity, when the resulting negative value becomes more negative than the most negative representable number.

In both cases, the program simply continues with its execution!

10 / 0;         // =>  Infinity
-10 / 0;        // => -Infinity
2 / +0;         // => +Infinity
2 / -0;         // => -Infinity

Notice the -0 in the last statement. Negative 0 means it is a negative value closer to 0, but the value is so small that it cannot be represented with available precision. For instance, when you take -Number.MIN_VALUE (the smallest possible negative number, i.e. -5e-324) divided by 5, you get -0. Similarly, -1 divided by Infinity returns -0. Note that according to IEEE 754 specification, -0 is equal to 0

In JavaScript when an arithmetic operation fails it does not throw an error; instead it returns a special numeric value, called NaN (for Not a Number), and the program happily continues with execution. The following operations all result in NaN:

Infinity / Infinity;   // => Nan. 
0 / 0;                 // => Nan.
"Hello" / 1;           // => Nan. "Hello" cannot be converted to number
Math.sqrt(-1);         // => Nan.
NaN / 0;               // => Nan. Any operation with NaN results in NaN

The JavaScript typeof operator does not distinguish between NaN and numbers, therefore the expression typeof NaN === "number" returns true. Furthermore, NaN does not compare equal to any number, including a comparison with itself, thus NaN == NaN returns false.

You need to be aware how NaN can affect computations which involves multiple steps. If you have a sequence of arithmetic operations and you get NaN as the final result, it means that either one of the initial inputs was NaN or NaN is produced somewhere in the chain.

The built-in function isNaN is used to determine whether a given value is NaN. It will return true if it is, and false if not. When a value is confirmed to be NaN, it is up to you how you deal with the value. You could do something like this (set it to zero):

var profit = NaN;
if (isNaN(profit)) {
    profit = 0;
}

Rather than using isNaN, a better approach would be to use the built-in function isFinite to determine whether a value can be used as a number or not. This function checks for both Infinity and NaN. Before calling isFinite make sure that the value passed is actually a number, like so:

var isNum = function isNumber(val) { 
    if (typeof val === "number") {
        return isFinite(val);
    }
    return false;
}
var n = 3.6;
alert(isNumber(n));   // => true
n = NaN;
alert(isNumber(n));   // => false
n = Infinity;
alert(isNumber(n));   // => false
Run

JavaScript Rounding Limitations

In terms of numeric precision, JavaScript may not give you the exact values you would expect.

0.119 / 100;    // => evaluates to 0.0011899999999999999
0.14 / 100;     // => evaluates to 0.0014000000000000002

The reason for these rounding imprecisions is that JavaScript uses a binary floating-point format for number. Binary floating-point representations can exactly represent fractions like 1/16, and 1/32, 1/64, 1/128, but not fractions like 1/100, 1/10 which are very common in monetary calculations. This can cause some rounding limitations like the examples below:

var diff1 = .5 - .4;   // => 0.09999999999999998 
var diff2 = .4 - .3;   // => 0.10000000000000003
alert(diff1 == diff2); // => false, the values are not the same
Run

The last statement can be rather disheartening. Both diff1 and diff2 are very close to .1, but not exact. So, be aware of JavaScript's internal number representations.





Using the ++ and -- operators

In the C language, copying a string is frequently coded as the following one-liner:

while (*str1++ = *str2++);

This code tends to be tricky and confuse developers that are not too familiar with the 'pre' and 'post' nature of increment and decrement operators. Although JavaScript does not support pointers, the terseness of the ++ and -- operators is something that will need to be looked at carefully. For example, even an experienced JavaScript programmer will need some time to figure out what the following statement does:

var m = 7;
m = m++ + --m;
alert(m)        // what is the value of m?
Run

Clearly, this makes the code unnecessarily complex and hard to understand. It is best to use the ++ and -- operators on a single line which enhances program readability. For example:

count++;
elements[count] = 10;

Anything beyond that can be confusing; chances of making typos are high.

However, JavaScript loops can safely use the increment operators within a for-loop because it is standard practice and usually does not cause confusion.

for(var i = 0, j = cost.length; i < 5; i++, j++)
{
    cost[j] = val[i];
}

If you minify JavaScript code, be very careful when using ++ and -- operators. Minimizers remove unnecessary whitespace and comments from your JavaScript code. As an example, it may translate i + ++j into i+++j. The compiler then treats the resulting expression as
i++ + j which is incorrect. Fortunately, this is easily corrected by adding parentheses like
so: i + (++j). So the lesson here is to always add parenthesis to make your intentions clear.

It is also good practice to run JSLint before minifying your code, as it checks for these and other potential problems related to the ++ and -- operators.





Using the == versus the strict === operator

The == operator compares the values of its operands. If their values are equal, it returns true. If the operands have different data types, JavaScript attempts to convert these to an appropriate type then compares their values. Consider this:

alert("1" == 1);       // => true
Run

Here the string "1" is compared to the numeric 1. JavaScript converts the string numeric literal to a number value. Since they are equal, it returns true. How about this:

alert(false == "0");   // => true
Run

This returns true. In this case, both operands are converted to numbers. Boolean true values are converted to 1 and false to 0. And the string "0" is converted to the number 0. Following the conversions JavaScript compares 0 == 0 and returns true.

Here are a few more cases:

alert(null == undefined);    // => true
alert(true == "1");          // => true
alert("9" < "P");            // => true 
Run

In the last expression, the ASCII values for numbers are lower than those for letters, returning true.

The rules of data conversion with the == operator are complex and hard to remember. This can easily lead to bugs. Fortunately JavaScript offers an alternative, called the strict equality operator (===) which does not convert data when testing for equality. It only returns true when 1) the operands being compared are of the same type and 2) their values are the same. Here are some examples:

alert("1" === 1);           // => false
alert(true === !false);     // => true
Run

If both operands are objects and if they refer to the same object, then JavaScript returns true. Let's see how this works with, say, arrays:

var ref1 = [10, 20];            // an array
var ref2 = [10, 20];            // a second array
alert(ref1 == ref2);            // => false
alert(ref1 === ref2);           // => false
Run

Here ref1 == ref2 returns false, because they reference different arrays. The strict comparison ref1 === ref2 also return false because, although they have the same values, these are two different arrays in memory.

As in many other languages, JavaScript strings are immutable meaning that the contents of a string object cannot be changed after the object is created, although the syntax makes it appear as if you can do this. Let's see how this affects == and === operations:

var str1 = "Hello World";       // a string
var str2 = "Hello" + " World";  // another string
alert(str1 == str2);            // => true
alert(str1 === str2)            // => true
Run

Here str1 and str2 reference the same immutable "Hello World" string and therefore both == and === return true.

How about comparing string objects created with the String constructor and with a string literal?

alert("Hello" == new String("Hello"));    // => true
alert("Hello" === new String("Hello"));   // => false
Run

The == operator converts these objects on either side to the same type and then returns true because their values are the same. The === operator understands that the objects are not of the same type and therefore immediately returns false without even looking at their values.





Bitwise operators in JavaScript

The table below summarizes the bitwise operators in JavaScript:

Operator Usage Result
Bitwise AND a & b Returns 1 for each bit position where both operands are 1
Bitwise OR a | b Returns 1 for each bit position where either operand is 1
Bitwise XOR a ^ b Returns 1 for each bit position where either but not both are 1
Left shift a << b Shifts in binary fashion all bits one position to the left; discarding the left bit and filling the right bit with 0.
Right shift a >> b Shifts in binary fashion all bits one position to the right, discarding the right bit. This operations maintains the original sign (+ or -).
0-fill right shift a >>> b Shifts in binary fashion all bits one position to the right, discarding the right bit and filling the left bit with 0.

JavaScript does not support an integer type. All numbers in JavaScript are stored in 64-bit floating point format i.e. double precision floating point. The bitwise operators that manipulate numbers at the bit level do not perform operations directly on this 64-bit floating-point representation. Instead, they coerce the numeric values to signed 32-bit integers, do the necessary operation, and again convert the result back to floating point format. This conversion has a performance impact.

You get the correct results for only up to 32 bits. During the conversion to 32-bit, the fractional part and any bits beyond the 32nd are dropped. If you have more bits than that, the value gets rounded to the nearest representable floating-point number.

var a = 0xFFFFFFFFF;     // => 36 bits all set to 1
var b = 0xFFFFFFFFF;     // => 36 bits all set to 1
var c = a & b;           // bitwise AND
alert(c);                // => -1
Run

You may expect that c's value has all 36 bits set to 1 following the bitwise & operation, but because of the conversion to 32-bits that is not the case. JavaScript converts to 32-bit, executes the bitwise AND operation, and the resulting 32-bits are all set to 1 which is equal to -1.

Let's look at an example with floating point numbers:

var a = 2.6;     // represented as bits 0010, fractional part discarded
var b = 6.2      // represented as bits 0110, fractional part discarded
var c = a & b;   // => bits 0010, which is equal to 2 
alert(c);        // => 2
Run

Strangely, if you use NaN, Infinity, or -Infinity as operands in bitwise operations, they are converted to 0.

In all C-like languages, bitwise operators are extremely fast. Until recently, they were slow in JavaScript but the latest versions of web browsers can JIT-compile JavaScript code. These operations have accelerated enough to be useful.

Bitwise manipulations are typically close to the hardware and therefore they don't come up very often in JavaScript programming.

A common mistake it to use bitwise & and | operators instead of logical && and || operators. This can lead to hard-to-detect bugs. Here is what may happen. Say we have a variable x with a value of 5 and you have mistakenly typed & instead of &&.

var x = 5;
if (x > 5 & x < 8) {
    alert(true);
} else {
    alert(false);
}
Run

This is false, which is the same if you had typed the && operator: if (x<=5 && x>7). Although we are getting the expected result, we have improperly used a logical & operator which is intended for bit-level operations only. Again, be aware of this mistake as it can lead to difficult to find bugs.