On this page
Objects and arrays
Creating objects
Objects are collections of key-value pairs. They are the most commonly used data structure in JavaScript for representing entities:
const product = {
name: 'Laptop',
price: 999,
available: true,
};When a variable name matches the property name, you can use the shorthand syntax:
const name = 'Laptop';
const price = 999;
const product = { name, price };
// Same as { name: name, price: price }Computed property names
You can use expressions as property keys by wrapping them in brackets:
const field = 'color';
const item = { [field]: 'red', [`${field}Code`]: '#ff0000' };
// { color: 'red', colorCode: '#ff0000' }This is especially useful when building objects dynamically from variables or function parameters.
Accessing properties
JavaScript offers two ways to read and write object properties:
const user = { name: 'Ana', age: 28 };
// Dot notation - clean and common
user.name; // 'Ana'
// Bracket notation - dynamic or special keys
user['age']; // 28
const key = 'name';
user[key]; // 'Ana'Use dot notation by default for readability. Use bracket notation when the key is dynamic, stored in a variable, or contains characters like spaces or hyphens.
Object utility methods
Object.keys(), Object.values(), Object.entries()
These static methods let you extract and iterate over an object's contents:
const config = { theme: 'dark', lang: 'en', debug: false };
Object.keys(config); // ['theme', 'lang', 'debug']
Object.values(config); // ['dark', 'en', false]
Object.entries(config);
// [['theme', 'dark'], ['lang', 'en'], ['debug', false]]Object.entries() is particularly powerful for iterating with for...of:
for (const [key, value] of Object.entries(config)) {
console.log(`${key} = ${value}`);
}Object.assign() and spread for merging
Both approaches merge properties from one or more source objects into a target:
// Object.assign - mutates the first argument
const defaults = { theme: 'light', lang: 'en' };
const prefs = { theme: 'dark' };
const merged = Object.assign({}, defaults, prefs);
// { theme: 'dark', lang: 'en' }
// Spread - cleaner, same result
const merged2 = { ...defaults, ...prefs };
// { theme: 'dark', lang: 'en' }[!WARNING] Both
Object.assign()and spread create shallow copies. Nested objects are still shared by reference. UsestructuredClone()when you need a deep copy.
Optional chaining
The optional chaining operator (?.) lets you safely access deeply nested properties without checking each level manually:
const user = { name: 'Ana', address: { city: 'Oruro' } };
// Without optional chaining (verbose)
const zip = user.address && user.address.zip;
// With optional chaining (clean)
const zip2 = user.address?.zip; // undefined
const street = user.location?.street; // undefined (no error)Combine it with the nullish coalescing operator (??) to provide fallback values:
const city = user.address?.city ?? 'Unknown';
// 'Oruro'[!TIP] Optional chaining also works with methods (
obj.method?.()) and arrays (arr?.[0]).
Getters and setters
Getters and setters let you define computed properties that behave like regular properties but run logic when accessed or assigned:
const account = {
_balance: 1000,
get balance() {
return `$${this._balance.toFixed(2)}`;
},
set balance(amount) {
if (amount < 0) throw new Error('Invalid amount');
this._balance = amount;
},
};
console.log(account.balance); // '$1000.00'
account.balance = 2500;
console.log(account.balance); // '$2500.00'They are useful for validation, formatting, and encapsulating internal state.
Destructuring
Destructuring allows you to extract values from objects and arrays into individual variables in a concise and elegant way.
Object destructuring
const user = { name: 'Ana', age: 28, role: 'admin' };
const { name, age } = user;Renaming variables during destructuring avoids naming conflicts:
const { name: userName, age: userAge } = user;
// userName = 'Ana', userAge = 28Default values are used when the property is undefined:
const { name, country = 'Bolivia' } = user;
// country = 'Bolivia' (not in user)Nested destructuring
Extract values from deeply nested objects in one step:
const company = {
name: 'Acme',
address: { city: 'Oruro', country: 'Bolivia' },
};
const { address: { city, country } } = company;
// city = 'Oruro', country = 'Bolivia'Array destructuring
const colors = ['red', 'green', 'blue', 'yellow'];
const [primary, secondary] = colors;
// primary = 'red', secondary = 'green'
// Skip elements
const [, , third] = colors;
// third = 'blue'Spread operator
The spread operator (...) expands an iterable (array, object) into individual elements. It is essential for immutable patterns:
// Copying arrays
const original = [1, 2, 3];
const copy = [...original];
// Merging arrays
const all = [...original, 4, 5];
// Copying objects
const user = { name: 'Ana', age: 28 };
const clone = { ...user };
// Merging objects (later properties override earlier ones)
const updated = { ...user, age: 29, role: 'admin' };Rest in destructuring and functions
The rest syntax (...) collects remaining elements into an array or object. It is the counterpart of spread:
Rest in arrays
const [first, ...remaining] = [10, 20, 30, 40];
// first = 10, remaining = [20, 30, 40]Rest in objects
const { name, ...details } = { name: 'Ana', age: 28, role: 'admin' };
// name = 'Ana', details = { age: 28, role: 'admin' }Rest parameters in functions
Rest parameters let a function accept any number of arguments as a real array:
function sum(...numbers) {
return numbers.reduce((acc, n) => acc + n, 0);
}
sum(1, 2, 3); // 6
sum(10, 20, 30, 40); // 100[!INFO] Rest parameters must always be the last parameter in the function signature:
function log(level, ...messages).
Multidimensional arrays
Arrays can contain other arrays, creating matrices or grids:
const matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
// Access: matrix[row][column]
console.log(matrix[0][2]); // 3
console.log(matrix[2][1]); // 8Iterate over all cells with nested loops:
for (const row of matrix) {
for (const cell of row) {
console.log(cell);
}
}Practice
- Use destructuring with default values: Given the object
{ name: 'Ana', age: 28 }, extractname,age, andcountrywith a default value of'Bolivia'using destructuring. Print all three values to the console. - Combine spread and optional chaining: Create a
userobject with a nestedaddress.streetproperty. Use spread to create a copy with a newage, and optional chaining with??to accessuser.contact?.phonewith a default value of'N/A'. - Iterate with Object.entries: Create a
scoresobject with 3 subjects and their grades. Iterate it withfor...ofandObject.entries(), printing"Subject: grade"for each one.
In the next lesson we will dive into array methods like map, filter, and reduce for powerful data transformations.
// Creating objects
const user = {
name: 'Ana',
age: 28,
skills: ['JavaScript', 'Angular'],
};
// Computed property names
const field = 'email';
const dynamic = { [field]: '[email protected]' };
// Accessing properties
console.log(user.name); // 'Ana'
console.log(user['age']); // 28
// Object.keys / values / entries
const keys = Object.keys(user);
// ['name', 'age', 'skills']
const values = Object.values(user);
// ['Ana', 28, ['JavaScript', 'Angular']]
// Destructuring with renaming and defaults
const { name: userName, role = 'student' } = user;
// userName = 'Ana', role = 'student'
// Spread - immutable copy and merge
const updated = { ...user, age: 29 };
const withEmail = { ...user, ...dynamic };
// Optional chaining + nullish coalescing
const city = user.address?.city ?? 'Not available';
// Rest parameters
function sum(...numbers) {
return numbers.reduce((acc, n) => acc + n, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
// Getters and setters
const account = {
_balance: 1000,
get balance() {
return `$${this._balance.toFixed(2)}`;
},
set balance(amount) {
if (amount < 0) throw new Error('Invalid amount');
this._balance = amount;
},
};
console.log(account.balance); // '$1000.00'
account.balance = 500;
// Nested destructuring
const company = {
name: 'Acme',
address: { city: 'Oruro', country: 'Bolivia' },
};
const { address: { city, country } } = company;
// city = 'Oruro', country = 'Bolivia'
// Multidimensional arrays
const matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
console.log(matrix[1][2]); // 6
// Array destructuring with rest
const [first, second, ...others] = [10, 20, 30, 40, 50];
// first = 10, second = 20, others = [30, 40, 50]
// Object.entries for iteration
const scores = { math: 95, science: 88, history: 72 };
for (const [subject, score] of Object.entries(scores)) {
console.log(`${subject}: ${score}`);
}
Sign in to track your progress