March 17, 2025

Variables and Data Types

var, let, const

One of the key features introduced with ES6 is the addition of let and const for variable declaration. Before ES6, var was the primary way to declare variables, but it had several issues.

Var

The scope of a variable defines where it can be accessed. Variables declared with var have global or function scope. If declared globally, the variable can be accessed anywhere in the window.

Example:

var greeter = "hey hi";
var greeter = "say Hello instead"; // Re-declaration is allowed

The issue with var is that re-declaring a variable can lead to unexpected outputs in code.

Let

let was introduced to improve var. It has block scope, meaning it can only be accessed within the block {} it was declared in. While let variables can be updated, they cannot be re-declared.

Example:

let message = "Hello";
message = "Hi"; // Allowed
let message = "Hey"; // Syntax Error

Another key difference is hoisting. When trying to access a hoisted variable before its declaration:

Const

Variables declared with const are constant, meaning their values cannot be updated or re-declared. Like let, const has block scope.

Example:

const PI = 3.1416;
PI = 3.14; // TypeError: Assignment to constant variable

However, objects and arrays declared with const can be modified:

const person = { name: "John" };
person.name = "Jane"; // Allowed

Primitive Types

Primitive types define immutable values and are represented at the lowest level of JavaScript. These types include:

Typetypeof return valueObject Wrapper
Null”object”N/A
Undefined”undefined”N/A
Boolean”boolean”Boolean
Number”number”Number
BigInt”bigint”BigInt
String”string”String
Symbol”symbol”Symbol

Null

Represents an intentional absence of a value.

let x = null;

Undefined

Represents an uninitialized variable.

let y;
console.log(y); // undefined

Boolean

Represents true or false values, commonly used in conditions.

let isActive = true;

Number

JavaScript uses double-precision 64-bit floating point numbers.

let num = 42;
let big = Number.MAX_SAFE_INTEGER;

Special values:

console.log(1 / 0); // Infinity
console.log(-1 / 0); // -Infinity
console.log(0 / 0); // NaN

BigInt

For handling integers beyond Number.MAX_SAFE_INTEGER.

let bigInt = 123456789012345678901234567890n;

String

Textual data, immutable.

let greeting = "Hello, world!";

Symbol

A unique identifier, often used for object property keys.

let sym = Symbol("unique");

Reference Types

Unlike primitive types, reference types store memory addresses instead of values.

Objects

Objects store key-value pairs.

let person = {
  name: "Alice",
  age: 25,
};

Arrays

Ordered collections of values.

let numbers = [1, 2, 3, 4, 5];

Functions

A callable object.

function greet() {
  console.log("Hello");
}

Maps & Sets

Map: Stores key-value pairs.

Set: Stores unique values.

Example:

let myMap = new Map();
myMap.set("key", "value");

let mySet = new Set([1, 2, 3]);

These reference types allow JavaScript to manage complex data efficiently.

Template Literals

Template literals, introduced in ES6, allow for easier string interpolation and multi-line strings. These are enclosed in backticks (`) and support embedded expressions.

Basic String Interpolation

You can embed expressions directly inside template literals using ${} syntax:

let name = "Alice";
let greeting = `Hello, ${name}!`; // String interpolation
console.log(greeting); // "Hello, Alice!"

Multi-line Strings

Template literals also make it easier to work with multi-line strings:

let multilineString = `This is a
multi-line
string!`;
console.log(multilineString);
// Output:
// This is a
// multi-line
// string!

Expressions and Computations

Template literals allow more complex expressions inside ${}:

let a = 10;
let b = 20;
let result = `The sum of ${a} and ${b} is ${a + b}.`;
console.log(result); // "The sum of 10 and 20 is 30."

This feature improves code readability and minimizes the need for string concatenation.

Variable Naming

Choosing meaningful variable names is a crucial practice for writing readable and maintainable code. Here are some best practices and guidelines for variable naming in JavaScript:

Descriptive Names

Variables should be named in a way that clearly indicates what they represent. For example:

let firstName = "Alice"; // Clear and descriptive
let age = 30; // Describes the person's age

CamelCase Convention

In JavaScript, camelCase is commonly used for variable and function names. The first word starts with a lowercase letter, and each subsequent word starts with an uppercase letter.

let userAge = 25;
let userFullName = "John Doe";

Constants in Uppercase

For constants, it’s common practice to use all uppercase letters with underscores separating words.

const MAX_USERS = 100;
const API_URL = "https://api.example.com";

Avoid Reserved Keywords

Avoid using JavaScript reserved keywords like let, var, if, else, class, function, and others as variable names.

Meaningful, Yet Concise

Choose variable names that are both meaningful and concise to ensure clarity without unnecessary verbosity. For instance, count is better than counterVariable, and isActive is more informative than statusFlag.

Memory Reference

Primitive vs Reference Types

In JavaScript, variables can hold primitive values or reference values. This distinction plays a crucial role in how values are stored and manipulated in memory.

Primitive Types

Primitive types are directly stored in memory. When a variable is assigned a primitive value, the value itself is stored in the variable:

let x = 10; // x stores the value 10 directly in memory
let y = x; // y now stores a copy of x's value
x = 20; // Changing x does not affect y
console.log(x); // 20
console.log(y); // 10

In this example, x and y store independent values. Changes to x do not affect y.

Reference Types

Reference types (such as objects, arrays, and functions) are stored as references (memory addresses). When a variable is assigned a reference type value, it stores the address of the object in memory, not the actual object itself.

let obj1 = { name: "Alice" };
let obj2 = obj1; // obj2 now references the same object as obj1
obj1.name = "Bob"; // Changing obj1 will also affect obj2
console.log(obj1.name); // "Bob"
console.log(obj2.name); // "Bob"

Here, both obj1 and obj2 refer to the same object in memory. Changing the object through either reference affects both variables because they point to the same memory location.

Passing by Value vs Passing by Reference

When passing variables to functions:

Example for primitive types:

function changeValue(num) {
  num = 100;
}

let myNumber = 50;
changeValue(myNumber);
console.log(myNumber); // 50, original value is unchanged

Example for reference types:

function changeObject(obj) {
  obj.name = "Charlie";
}

let myObject = { name: "Alice" };
changeObject(myObject);
console.log(myObject.name); // "Charlie", the object is modified

In summary, understanding how JavaScript handles memory references is key to managing variables, especially when working with complex data types like objects and arrays.