Variables

By Seokhyeon Byun 10 min read

Note: This post is based on my old programming study notes when I taught myself.

Variable Declarations

JavaScript has three ways to declare variables:

var Declaration

  • Scope: Function-scoped or globally-scoped
  • Hoisting: Hoisted and initialized with undefined
  • Re-declaration: Allowed
  • Re-assignment: Allowed
var name = "John";
var name = "Jane"; // Re-declaration allowed
name = "Bob"; // Re-assignment allowed

function example() {
  var x = 1;
  if (true) {
    var x = 2; // Same variable (function-scoped)
    console.log(x); // 2
  }
  console.log(x); // 2
}

let Declaration

  • Scope: Block-scoped
  • Hoisting: Hoisted but not initialized (Temporal Dead Zone)
  • Re-declaration: Not allowed in same scope
  • Re-assignment: Allowed
let age = 25;
// let age = 30; // SyntaxError: Identifier 'age' has already been declared
age = 30; // Re-assignment allowed

function example() {
  let y = 1;
  if (true) {
    let y = 2; // Different variable (block-scoped)
    console.log(y); // 2
  }
  console.log(y); // 1
}

const Declaration

  • Scope: Block-scoped
  • Hoisting: Hoisted but not initialized (Temporal Dead Zone)
  • Re-declaration: Not allowed
  • Re-assignment: Not allowed (but objects/arrays can be mutated)
const PI = 3.14159;
// PI = 3.14; // TypeError: Assignment to constant variable

const person = { name: "John" };
person.name = "Jane"; // Allowed - mutating object properties
// person = {}; // TypeError: Assignment to constant variable

Variable Scopes

  • Global scope: Variables accessible throughout the program
  • Function scope: Variables accessible within the function
  • Block scope: Variables accessible within the block {}
  • Module scope: Variables accessible within the module file

JavaScript Data Types

Number Type

JavaScript has only one number type that represents both integers and floating-point numbers.

// Integer examples
let age = 25;
let temperature = -10;

// Floating-point examples
let price = 19.99;
let pi = 3.14159;

// Special numeric values
let infinity = Infinity;
let negInfinity = -Infinity;
let notANumber = NaN;

// Scientific notation
let bigNumber = 2.5e6; // 2,500,000
let smallNumber = 1e-6; // 0.000001

Important Notes:

  • JavaScript uses IEEE 754 double-precision floating-point format
  • Maximum safe integer: Number.MAX_SAFE_INTEGER (2^53 - 1)
  • For larger integers, use BigInt

Reference: Number Global Object

String Type

A sequence of characters representing text values.

// Different ways to create strings
let singleQuote = "Hello World";
let doubleQuote = "Hello World";
let templateLiteral = `Hello World`;

// Template literals with variables
let name = "John";
let age = 30;
let message = `My name is ${name} and I'm ${age} years old`;

// String methods
let text = "JavaScript";
console.log(text.length); // 10
console.log(text.toUpperCase()); // "JAVASCRIPT"
console.log(text.substring(0, 4)); // "Java"

Key Features:

  • Immutable - string methods return new strings
  • Template literals (backticks) allow variable interpolation
  • Rich set of built-in methods for manipulation

Boolean Type

Represents logical values: true or false.

let isStudent = true;
let isGraduated = false;

// Boolean conversion - Falsy values
console.log(Boolean(0)); // false
console.log(Boolean("")); // false
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
console.log(Boolean(NaN)); // false
console.log(Boolean(false)); // false

// Everything else is truthy
console.log(Boolean(1)); // true
console.log(Boolean("hello")); // true
console.log(Boolean([])); // true
console.log(Boolean({})); // true

Refer: MDN Falsy

Falsy Values: false, 0, -0(negative zero), 0n(bigint zero), ""(empty string), null, undefined, NaN(not a number) Truthy Values: Everything else

Null and Undefined Types

Null

Represents an intentional absence of any object value.

let data = null; // Explicitly set to null
console.log(typeof null); // "object" (known bug in JavaScript)
console.log(data === null); // true
console.log(data == undefined); // true (loose equality)
console.log(data === undefined); // false (strict equality)

Key Points:

  • Must be explicitly assigned
  • typeof null returns "object" (historical bug that can’t be fixed)
  • Represents “no value” or “empty value”

Undefined

Represents a variable that has been declared but not assigned a value.

let x; // Declared but not assigned
console.log(x); // undefined
console.log(typeof x); // "undefined"

function test(param) {
  console.log(param); // undefined if no argument passed
}

let obj = {};
console.log(obj.nonExistentProperty); // undefined

Key Points:

  • Default value for uninitialized variables
  • Returned when accessing non-existent object properties
  • Returned by functions that don’t explicitly return a value

Type Coercion and Comparison

Loose vs Strict Equality

  • Strict equality uses three equal symbols
  • Strict inequality uses one exclamation mark and two equal symbols
// Loose equality (==) performs type coercion
console.log(5 == "5"); // true
console.log(null == undefined); // true
console.log(0 == false); // true
console.log("" == false); // true

// Strict equality (===) no type coercion
console.log(5 === "5"); // false
console.log(null === undefined); // false
console.log(0 === false); // false
console.log("" === false); // false

Best Practice: Always use strict equality (===) and strict inequality (!==) to avoid unexpected behavior.

Type Checking

// Using typeof operator
console.log(typeof 42); // "number"
console.log(typeof "hello"); // "string"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object" (bug)
console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(typeof function () {}); // "function"

// Better array checking
console.log(Array.isArray([])); // true
console.log(Array.isArray({})); // false

Memory Management and Garbage Collection

JavaScript automatically manages memory through garbage collection.

How Garbage Collection Works

// Memory is allocated when objects are created
let obj = { name: "John", age: 30 }; // Memory allocated

// Memory is freed when objects are no longer referenced
obj = null; // Original object becomes eligible for garbage collection

// Circular references (potential memory leaks in older browsers)
function createCircularReference() {
  let obj1 = {};
  let obj2 = {};
  obj1.ref = obj2;
  obj2.ref = obj1;
  // Modern browsers handle this, but be aware
}

Key Points:

  • Automatic memory allocation and deallocation
  • Uses mark-and-sweep algorithm in modern browsers
  • Circular references are handled by modern garbage collectors
  • Be careful with closures holding references to large objects

Reference: Memory Management Documentation


Variable Naming Rules

JavaScript has specific rules for naming variables:

  1. First character: Must be a letter, underscore (_), or dollar sign ($)
  2. Cannot start with numbers: 1variable is invalid
  3. Subsequent characters: Can include letters, numbers, underscores, or dollar signs
  4. Case sensitive: myVariable and myvariable are different
  5. No length limit: Variable names can be any length
  6. No spaces allowed: Use camelCase or snake_case instead
  7. Readability matters: Choose descriptive names
// Valid variable names
let userName = "John";
let _privateVar = 42;
let $element = document.getElementById("test");
let user2 = "Jane";

// Invalid variable names
// let 2user = "Invalid"; // Cannot start with number
// let user name = "Invalid"; // No spaces allowed
// let user-name = "Invalid"; // Hyphens not allowed

Advanced Variable Concepts

NaN (Not-a-Number)

NaN is a special numeric value representing an invalid number.

// Common situations that return NaN
console.log(parseInt("hello")); // NaN
console.log(Number(undefined)); // NaN
console.log(Math.sqrt(-1)); // NaN
console.log(0 / 0); // NaN
console.log("text" * 2); // NaN

// Check for NaN
console.log(isNaN(NaN)); // true
console.log(Number.isNaN(NaN)); // true (more reliable)
console.log(NaN === NaN); // false (NaN is not equal to itself)

Key Points:

  • NaN is the only value in JavaScript that is not equal to itself
  • Use Number.isNaN() for reliable NaN checking
  • Result of failed number conversion or invalid math operations

Arrays

Arrays are ordered collections that can hold multiple data types.

// Array creation
let fruits = ["apple", "banana", "orange"];
let mixed = [1, "hello", true, null, { name: "John" }];
let empty = new Array(5); // Creates array with 5 empty slots

// Array properties and methods
console.log(fruits.length); // 3
fruits.push("grape"); // Add to end
fruits.pop(); // Remove from end
fruits.unshift("mango"); // Add to beginning
fruits.shift(); // Remove from beginning

// Important array methods for interviews
let numbers = [1, 2, 3, 4, 5];
let doubled = numbers.map((x) => x * 2); // [2, 4, 6, 8, 10]
let evens = numbers.filter((x) => x % 2 === 0); // [2, 4]
let sum = numbers.reduce((acc, curr) => acc + curr, 0); // 15

// Array destructuring
let [first, second, ...rest] = fruits;
console.log(first); // First element
console.log(rest); // Remaining elements as array

Objects

Objects are collections of key-value pairs (properties).

// Object literal syntax
const person = {
  name: "John",
  age: 30,
  city: "New York",
  greet: function () {
    return `Hello, I'm ${this.name}`;
  },
};

// Accessing properties
console.log(person.name); // Dot notation
console.log(person["age"]); // Bracket notation
console.log(person.greet()); // Method call

// Object destructuring
const { name, age } = person;
console.log(name); // "John"

// Dynamic property names
const key = "profession";
const developer = {
  name: "Jane",
  [key]: "Software Engineer", // Dynamic key
};

// Object vs JSON
// Object literal: {name: "John", age: 30}
// JSON: {"name": "John", "age": 30} // Keys must be double-quoted

Reference vs Value Types

Understanding how JavaScript handles different data types in memory.

// Primitive types (passed by value)
let a = 5;
let b = a; // b gets a copy of a's value
a = 10;
console.log(b); // 5 (unchanged)

// Objects (passed by reference)
let obj1 = { count: 5 };
let obj2 = obj1; // obj2 references the same object
obj1.count = 10;
console.log(obj2.count); // 10 (changed because same reference)

// Array reference example
let arr1 = [1, 2, 3];
let arr2 = arr1; // Same reference
let arr3 = [...arr1]; // New array with copied values
arr1.push(4);
console.log(arr2); // [1, 2, 3, 4] (affected)
console.log(arr3); // [1, 2, 3] (not affected)

Template Literals

Modern string syntax with embedded expressions and multi-line support.

// Basic template literal
const name = "John";
const age = 30;
const message = `Hello, I'm ${name} and I'm ${age} years old.`;

// Multi-line strings
const multiLine = `
  This is line 1
  This is line 2
  This is line 3
`;

// Expression evaluation
const a = 10;
const b = 20;
const result = `The sum of ${a} and ${b} is ${a + b}`;

// Tagged templates (advanced)
function highlight(strings, ...values) {
  return strings.reduce((result, string, i) => {
    return result + string + (values[i] ? `<mark>${values[i]}</mark>` : "");
  }, "");
}

const highlighted = highlight`Hello ${name}, you are ${age} years old!`;

The new Operator and this Keyword

Understanding object creation and context binding.

// Constructor function
function Person(name, age) {
  this.name = name;
  this.age = age;
  this.greet = function () {
    return `Hello, I'm ${this.name}`;
  };
}

// Using new operator
const john = new Person("John", 30);
console.log(john.greet()); // "Hello, I'm John"

// What happens without 'new'?
const jane = Person("Jane", 25); // DON'T DO THIS
console.log(jane); // undefined
console.log(window.name); // "Jane" (global pollution)

// this context examples
const obj = {
  name: "Object",
  regular: function () {
    return this.name; // 'this' refers to obj
  },
  arrow: () => {
    return this.name; // 'this' refers to global/window
  },
};

console.log(obj.regular()); // "Object"
console.log(obj.arrow()); // undefined (or global context)