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:
var
returnsundefined
let
throws aReferenceError
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:
Type | typeof return value | Object 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:
- Primitive types are passed by value: the function receives a copy of the value.
- Reference types are passed by reference: the function receives a reference to the original object, allowing the object to be modified.
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.