DEV Community

Cover image for Weird JS
Rahul Kumar Jha
Rahul Kumar Jha

Posted on • Edited on

Weird JS

null vs undefined in JavaScript

  • 1. undefined: Variable declared but not assigned.
  • 2. null: Variable intentionally set to no value.
let a;
console.log(a); // undefined

let b = null;
console.log(b); // null
Enter fullscreen mode Exit fullscreen mode

Summary:
undefined = automatic (I haven't given a value yet)
null = intentional (I specifically have no value)

var vs let

Scope

In JavaScript:

  • var is function-scoped. This means that a variable declared with var is accessible anywhere within the function in which it is declared, regardless of block boundaries (like { ... }).

  • let is block-scoped. This means that a variable declared with let is only accessible within the block (e.g., inside { ... }) where it is defined.

Example:

function hi() {
  {
    let a = 10;
    var b = 20; // 'b' is function-scoped, not block-scoped
  }

  console.log(b); // 20 - accessible, because 'b' is function-scoped
  console.log(a); // ReferenceError: a is not defined - 'a' is block-scoped
}

hi();
Enter fullscreen mode Exit fullscreen mode
  • b is accessible outside the block because var ignores the block and only cares about the function scope.

  • a is not accessible outside the block because let restricts its visibility to the block where it is defined.

Hoisting

  • Both var and let are hoisted to the top of their scope. However, var is initialized with undefined during hoisting, so you can reference it before its declaration (but its value will be undefined).
  • let is not initialized during hoisting. If you try to access it before its declaration, you get a ReferenceError due to the "temporal dead zone."

Example:

console.log(a); // undefined - 'a' is hoisted and initialized
console.log(b); // ReferenceError: Cannot access 'b' before initialization

var a = 1;
let b = 2;
Enter fullscreen mode Exit fullscreen mode

Redeclaration

var can be redeclared within the same scope without error.
let cannot be redeclared within the same scope. Attempting to do so results in a SyntaxError.

let a = 2;
let a = 3; // SyntaxError: Identifier 'a' has already been declared

var b = 2;
var b = 3; // No error, 'b' is simply reassigned
Enter fullscreen mode Exit fullscreen mode

Summary:

  • var is function-scoped.
  • let is block-scoped.
  • Variables declared with var inside a block are still accessible anywhere in the function.
  • Variables declared with let inside a block are only accessible within that block.
  • var is hoisted and initialized as undefined.
  • let is hoisted but not initialized; accessing it before declaration throws a ReferenceError due to the temporal dead zone.
  • var: can be redeclared in the same scope
  • let: cannot be redeclared in the same scope (will throw a SyntaxError)

Using let leads to safer, clearer, and more maintainable code compared to var.

Weird Implicit Conversion (Type Coercion)

JavaScript uses implicit type coercion to automatically convert between strings and numbers during operations, which can lead to unexpected results—especially with +, -, or *. To avoid surprises, use explicit type coercion to control how your values are converted.

const a = "3";
const b = 2;

console.log(a + b); // "32"  (implicit coercion: string concatenation)
console.log(a - b); // 1     (implicit coercion: numeric subtraction)
console.log(a * b); // 6     (implicit coercion: numeric multiplication)

// Avoid surprises with explicit type coercion:
console.log(parseInt(a) + b);      // 5 (explicit coercion: numeric addition)
console.log(a + b.toString());     // "32" (explicit coercion: string concatenation)
Enter fullscreen mode Exit fullscreen mode

Tip:
Use parseInt() or Number() for explicit numeric conversion, and toString() for explicit string conversion, so your results are always clear and predictable.

What the Heck is NaN in JavaScript?

Ever seen NaN in JavaScript? It stands for "Not-a-Number"—but it’s actually a special value of type number!

const a = "hello";
const b = parseInt(a); // NaN

console.log(typeof NaN); // "number" (wait, what?)
console.log(NaN == NaN); // false (seriously?)
Enter fullscreen mode Exit fullscreen mode
  • NaN means a failed numeric conversion.
  • Weirdly, NaN is a number, but it’s not equal to itself!

How do you check for NaN?

console.log(isNaN(b)); // true

Tip:
Always use isNaN() to check for NaN—it’s the only reliable way!

Equality and Type Coercion (== vs === or != vs !==) in JavaScript

In JavaScript, == and != compare values with type coercion, converting types if needed. === and !== compare both value and type, so no conversion happens.

// Equality
console.log(0 == false);    // true
console.log(0 === false);   // false

console.log("" == 0);       // true
console.log("" === 0);      // false

console.log("" == false);   // true
console.log("" === false);  // false

console.log("1" == 1);      // true
console.log("1" === 1);     // false

// Not Equality
console.log(0 != false);    // false
console.log(0 !== false);   // true

console.log("" != 0);       // false
console.log("" !== 0);      // true

console.log("" != false);   // false
console.log("" !== false);  // true

console.log("1" != 1);      // false
console.log("1" !== 1);     // true
Enter fullscreen mode Exit fullscreen mode

Tip:
Prefer === and !== for clear and predictable comparisons.

Top comments (0)