Nullish Coalescing(??) vs OR (||)

Nullish Coalescing(??) vs OR (||)

To get more clarity on how nullish coalescing (??) works, it would be wiser to compare it with the OR operator (||) and understand.

Before we head towards the blog's main topic, I want to brief you about Falsy values in javascript.

Falsy & Truthy values in Javascript:

In this topic we will talk about:

  • Primitive Data Types

  • Falsy values

  • Truthy values

Primitive Data Types:

Primitive data types are a set of basic data types in javascript.
There are seven primitive datatypes in javascript:

  • Null

  • Number

  • String

  • Symbol

  • Boolean

  • BigInt

  • Undefined

const a = null;
console.log(typeof(a)); // Output: object

const b = 12;
console.log(typeof(b)); // Output: number

const c = "abhay";
console.log(typeof(c)); // Output: string

const d = Symbol("Hello");
console.log(typeof(d)); // Output: symbol

const e = true;
console.log(typeof(e)); // Output: boolean

const f = BigInt(123456767544);
console.log(typeof(f)); // Output: bigint

const g = undefined;
console.log(typeof(g)); // Output: undefined

We will discuss them slowly as we go through the blog until then you should know that there are seven primitive data types whereas an object is a non-primitive datatype in javascript. Talking about an array is also a non-primitive data type.

const array = [1,2,3,4,5,6];
console.log(typeof(array)); //Output: object

Falsy values:

A falsy value in javascript is a value that is considered to be false in boolean context.

So basically in javascript, booleans are the primitive data types that can either be true or false depending on the result of evaluating an expression or condition.

console.log(3>0);
//Output: true
console.log(3<0);
//Output: false

As we can see in the above example we have boolean values (true and false) under the respective conditions.

Javascript has characterized a set of values that are considered to be false.
These are the falsy values in javascript:

ValueDescription
falseThe keyword false
0,-0The number 0(positive and negative both)
"", '', `` Empty string
nullabsence of any value
undefinedabsence of the value until we assign it some value
NaNnot a number (illegal numbers)

From the above-mentioned falsy values I would like to talk about the following values:

Undefined:

When we declare a variable and forget to assign it some value, it will always be undefined until we initialize/assign it with some value, which can be a string, number, object, array, etc.

let x; //Declared x but not assigned some value to it
console.log(x); //Output: undefined, as x has no value been assigned or x has not been initialized yet

Here we declared variable x but did not assign it some value so when we try to access variable x it will show undefined in the output.

But if in the future we assign it with some value, it will not show undefined.

//in continuation with the above example
x = "abhay"; //we initialized x that we declared in the previous code snippet
console.log(x); // Output: abhay

Null:

Suppose we are trying to access some value (for example we are trying to access productCode) from a server but the value (productCode) does not exist in the server database, so in this case it will show us null as there does not exist any value (productCode) in the server.

Null vs Undefined:

let y; // y is declared but not assigned any value so in this case javascript automatically sets undefined until it is assigned some value by the user
let x = null; // but in the case of null the user has to manually set the value of the variable to null.

console.log(y); // Output: undefined
console.log(typeof(y)); // Output: undefined

console.log(x); // Output: Null
console.log(typeof(x)); // Output: Object

console.log(x == y); // Output: true, takes only values into consideration
console.log(x === y); // Output: false, takes values as well as there data type into consideration

Loose equality operator(==) returns true because it assumes that both x and y do not have any value. But in the case of strict equality operator(===), it takes their data types also into consideration which is different for undefined and null hence it returns false.

We will talk more about null and undefined after NaN(not a number).

NaN (not a number):

console.log(typeof(NaN)); // Output: number

console.log(2 * "haule"); // Output: NaN

As we can see in the above example, we are trying to multiply a number( 2 in this case ) with a string ("haule"). So in this case, we would not get a number and hence it returns NaN (Not a Number).

We can classify numbers as legal numbers and illegal numbers. In the above example, "haule" (a string) will be treated as an illegal number whereas 2 is a legal number.

let a = "50"; // datatype is string in this case as we have wrapped number inside double inverted comma
let b = 10; // it is a number
let c = "haule"; // again a string
console.log(a/b); // a/b = "50"/10 Output: 5

console.log(a/c); // a/c = "50"/"haule" Output: NaN

If there's only a number inside a string data type as shown above let a = "50" then it will be considered as a legal number and it will be converted to a number by javascript internally through toNumber() (it is an in-built function in javascript) function.

In the first console.log(a/b) the value of a ("50" is a legal number) will be converted to a number through toNumber() function internally by javascript and finally, the operation will look like 50/10 hence the result is 5.

In the second console.log(a/c) the value of c ("haule" is an illegal number) cannot be converted into a number and when we perform any operation with an illegal number it will return NaN (not a number).

let length = 10;
let breadth; // undefined as we have not assigned it some value
let area = length * breadth; // area = 10 * undefined
console.log(area); // Output: NaN

In the above example when we try to multiply a number with undefined (10 * undefined), javascript internally uses a function toNumber() and converts undefined to NaN and when we multiply NaN with a number it will result in NaN.

let length2 = 20;
let breadth2 = null; // we have manually assigned null value to the variable
let area = length2 * breadth2; // area = 20 * null

console.log(area); // Output: 0

In the above example, toNumber() converts Null to 0 so when we calculate area (20 * 0) we get 0 as the output.

Undefined:

  • This means the variable has been declared
    but its value has not been assigned.

  • returns NaN on performing an arithmetic
    operation.

  • undefined value has an undefined data type

Null:

  • This means an empty value, the value
    does not exist.

  • converts to 0 then operate.

  • The data type of value null is an object.

Truthy value:

Truthy values are considered true in the boolean context, anything other than falsy is considered a truthy value. For instance string, number, true (boolean value) etc.

OR operator (||) :

Compares two conditions and returns true or false based on the result of each condition.

const a = 3;
const b = -2;
console.log(a>0 || b>0); // 3>0 is true whereas -2>0 is false Output: true

In OR if one of the conditions is true as in the above case then it will return true.

const a = -3;
const b = 2;
console.log(a>0 || b>0); // -3>0 is false and 2>0 is true Output: true

Similarly in the above case, one condition was true that's why it returns true.

const a = -3;
const b = -2;
console.log(a>0 || b>0); // -3>0 is false and -2>0 is also false Output: false

In the above example, neither of the two conditions was true so the output is false.

const a = 3;
const b = 2;
console.log(a>0 || b>0); // 3>0 is true and 2>0 is true Output: true

Here both conditions are true so the output is true.

const a = 1; // number data type hence truthy value
const b = 0; // 0 is considered as falsy value
console.log(a || b); //Output: 1

Here, 1 is a truthy value (true in boolean context) and 0 is a falsy value (false in boolean context), so it returns true (1 is considered to be true as it is a truthy value).

const a = "abhay"; // string
const b = false; // false which is a value of boolean data type

console.log(a || b); // Output: abhay

Here, string ("abhay") is a truthy value (true in boolean context) and boolean (false) is a falsy value (false in boolean context), hence it returns a string (abhay).

 const a = 123; // number
 const b; // will be assigned undefined value as there is no initialization

console.log(a || b); // Output: 123

Here, number (123) is a truthy value (true in a boolean context) and variable b will be assigned an undefined value which is considered to be a falsy value, hence the output will be 123 (as it is considered to be true in boolean context).

Nullish coalescing (??) :

Let's see its syntax first:

let val = "abhay"; // string
const example = val ?? 10; // 10 is the default value

console.log(example); // output: abhay

nullish coalescing (??) operator checks whether the value (val in the above case) is undefined or null, and returns the default value if the value (val) is undefined or null. But in the above code, val is a string so it will return (abhay) only.

Note that nullish coalescing operator (??) considers null and undefined only as falsy values.

//In case of val is undefined
let val; // only declaration so it will be undefined until assigned value
const example = val ?? 10; // 10 is the default value

console.log(example); // output: 10
//In case of val is null
let val = null; // here we are manually assigning null value to the variable
const example = val ?? 10; // 10 is the default value

console.log(example); // output: 10

OR operator (||) vs nullish coalescing (??) :

let valueOne = 0;
let myNumber = valueOne || 10; 
let myNumber2 = valueOne ?? 10;

console.log(myNumber); // Output: 10
console.log(myNumber2); // Output: 0

Why is the output different for both the console in above code?

We earlier talked about falsy values, now is the time to apply its concept here.
OR operator considers all falsy values to be false in boolean context, that's why while comparing 0 with 10 in myNumber we know that 0 is a falsy value whereas 10 is a number and it is a truthy value so it returns 10 as it is the truthy value (true in boolean context).

While in the case of the second console.log(myNumber2), we are accessing myNumber2 which has the same values being compared (0 and 10) but with nullish coalescing operator. Nullish coalescing only considers null and undefined as falsy values which will be considered as false in boolean context. That's why it prints 0 as it is not a falsy value as per nullish coalescing operator.

let valueOne = false;
let myNumber1 = valueOne || "haule"; // false is a falsy value for OR operator 
let myNumber2 = valueOne ?? "haule"; // false is not considered to be falsy value in case of nullish coalescing operator

console.log(myNumber1); // Output: haule
console.log(myNumber2); // Output: false

Summary:

  • Primitive data type (nnbbssu) : null, number, boolean, bigInt, string, symbol, undefined.

  • Falsy values: 0, undefined, null, false, "" (empty string), NaN.
    Considered as false in boolean context.
    Note: empty array ([]) or empty object ({}) is not a falsy value only an empty string ("") is considered as a falsy value.

  • Truthy values: All values except falsy values.Considered as true in boolean context.

  • OR operator: returns true if any of the two values being compared is true or both of them are true. All falsy values are considered false in a boolean context.

  • nullish coalescing: null and undefined falsy values are only considered as false values in a boolean context. If the null and undefined value is present it returns the default value.

Reference: