JavaScript Objects & Arrays

Objects and arrays are fundamental data structures in JavaScript. Objects store collections of data as key-value pairs, while arrays store ordered collections of values. Understanding how to work with these structures is essential for effective JavaScript programming.

JavaScript Objects

Objects in JavaScript are collections of key-value pairs, where each key is a string (or Symbol) and each value can be any data type, including other objects.

Creating Objects

// Object literal notation
const person = {
  firstName: "John",
  lastName: "Doe",
  age: 30,
  email: "john.doe@example.com",
  isEmployed: true,
  hobbies: ["reading", "swimming", "coding"]
};

// Empty object
const emptyObject = {};

// Using the Object constructor
const anotherObject = new Object();
anotherObject.property = "value";

Accessing Object Properties

// Dot notation
console.log(person.firstName);  // "John"
console.log(person.age);        // 30

// Bracket notation
console.log(person["lastName"]); // "Doe"

// Bracket notation is useful when property names are dynamic
const propertyName = "email";
console.log(person[propertyName]);  // "john.doe@example.com"

// Accessing nested properties
console.log(person.hobbies[0]);  // "reading"

Modifying Objects

// Adding new properties
person.address = "123 Main St";
person["phoneNumber"] = "555-1234";

// Modifying existing properties
person.age = 31;
person["isEmployed"] = false;

// Deleting properties
delete person.email;

// Checking if a property exists
console.log("firstName" in person);  // true
console.log("middleName" in person); // false

// hasOwnProperty method
console.log(person.hasOwnProperty("age"));  // true

Object Methods

// Adding methods to objects
const calculator = {
  add: function(a, b) {
    return a + b;
  },

  // Shorthand method syntax (ES6)
  subtract(a, b) {
    return a - b;
  },

  // Arrow function as method (note: different 'this' behavior)
  multiply: (a, b) => a * b
};

console.log(calculator.add(5, 3));       // 8
console.log(calculator.subtract(10, 4)); // 6
console.log(calculator.multiply(2, 6));  // 12

The 'this' Keyword in Objects

const person = {
  firstName: "John",
  lastName: "Doe",

  // Regular function as method
  getFullName: function() {
    return this.firstName + " " + this.lastName;
  },

  // Arrow function doesn't have its own 'this'
  getArrowFullName: () => {
    // 'this' refers to the outer scope, not the person object
    return this.firstName + " " + this.lastName;  // Will not work as expected
  }
};

console.log(person.getFullName());      // "John Doe"
console.log(person.getArrowFullName()); // "undefined undefined" (or error)

Warning: Arrow functions don't have their own this context. When used as object methods, they inherit this from the surrounding scope, which is usually not what you want. Use regular functions for object methods when you need to access the object with this.

Object Destructuring (ES6)

const person = {
  firstName: "John",
  lastName: "Doe",
  age: 30,
  address: {
    street: "123 Main St",
    city: "Anytown",
    country: "USA"
  }
};

// Basic destructuring
const { firstName, lastName } = person;
console.log(firstName);  // "John"
console.log(lastName);   // "Doe"

// Destructuring with new variable names
const { firstName: fName, lastName: lName } = person;
console.log(fName);  // "John"
console.log(lName);  // "Doe"

// Nested destructuring
const { address: { city, country } } = person;
console.log(city);     // "Anytown"
console.log(country);  // "USA"

// Default values
const { middleName = "N/A" } = person;
console.log(middleName);  // "N/A" (since it doesn't exist in person)

Object Methods from Object.prototype

const person = {
              firstName: "John",
              lastName: "Doe",
              age: 30
            };

            // Check if property exists
            console.log(person.hasOwnProperty("firstName"));  // true
            console.log(person.hasOwnProperty("toString"));   // false (inherited)

            // Convert to string
            console.log(person.toString());  // "[object Object]"

            // Get property names
            console.log(Object.keys(person));  // ["firstName", "lastName", "age"]

            // Get property values
            console.log(Object.values(person));  // ["John", "Doe", 30]

            // Get key-value pairs as arrays
            console.log(Object.entries(person));
            // [['firstName', 'John'], ['lastName', 'Doe'], ['age', 30]]
            

Object.assign and Spread Operator

// Copying objects with Object.assign
const person = { firstName: "John", lastName: "Doe" };
const details = { age: 30, job: "Developer" };

// Merge objects
const merged = Object.assign({}, person, details);
console.log(merged);  
// { firstName: "John", lastName: "Doe", age: 30, job: "Developer" }

// Spread operator (ES6)
const mergedWithSpread = { ...person, ...details };
console.log(mergedWithSpread);  
// { firstName: "John", lastName: "Doe", age: 30, job: "Developer" }

// Creating a copy with modifications
const updatedPerson = { ...person, age: 31, firstName: "Jane" };
console.log(updatedPerson);  
// { firstName: "Jane", lastName: "Doe", age: 31 }

Note: Both Object.assign and the spread operator create shallow copies. Nested objects are still referenced, not duplicated.

JavaScript Arrays

Arrays in JavaScript are ordered collections of values. They can store values of any type, including other arrays and objects.

Creating Arrays

// Array literal notation
const fruits = ["apple", "banana", "orange"];

// Empty array
const emptyArray = [];

// Array with mixed types
const mixed = [1, "hello", true, { name: "John" }, [1, 2, 3]];

// Using the Array constructor
const numbers = new Array(1, 2, 3, 4, 5);

// Creating an array with a specific length
const zeros = new Array(5);  // Creates an array with 5 empty slots

Accessing Array Elements

const fruits = ["apple", "banana", "orange", "mango"];

// Using index (zero-based)
console.log(fruits[0]);  // "apple"
console.log(fruits[2]);  // "orange"

// Getting the last element
console.log(fruits[fruits.length - 1]);  // "mango"

// Using at() method (ES2022)
console.log(fruits.at(-1));  // "mango" (last element)
console.log(fruits.at(-2));  // "orange" (second-to-last element)

// Accessing elements in nested arrays
const matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
console.log(matrix[1][2]);  // 6

Modifying Arrays

const fruits = ["apple", "banana", "orange"];

// Changing an element
fruits[1] = "grape";
console.log(fruits);  // ["apple", "grape", "orange"]

// Adding elements to the end
fruits.push("mango");
console.log(fruits);  // ["apple", "grape", "orange", "mango"]

// Adding elements to the beginning
fruits.unshift("pear");
console.log(fruits);  // ["pear", "apple", "grape", "orange", "mango"]

// Removing the last element
const lastFruit = fruits.pop();
console.log(lastFruit);  // "mango"
console.log(fruits);     // ["pear", "apple", "grape", "orange"]

// Removing the first element
const firstFruit = fruits.shift();
console.log(firstFruit);  // "pear"
console.log(fruits);      // ["apple", "grape", "orange"]

// Removing elements at a specific position
const removed = fruits.splice(1, 1);  // Remove 1 element at index 1
console.log(removed);  // ["grape"]
console.log(fruits);   // ["apple", "orange"]

// Adding elements at a specific position
fruits.splice(1, 0, "banana", "kiwi");  // Insert at index 1, remove 0 elements
console.log(fruits);  // ["apple", "banana", "kiwi", "orange"]

Array Methods

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

// forEach - executes a function for each element
numbers.forEach(num => console.log(num * 2));  // Outputs: 2, 4, 6, 8, 10

// map - creates a new array by transforming each element
const doubled = numbers.map(num => num * 2);
console.log(doubled);  // [2, 4, 6, 8, 10]

// filter - creates a new array with elements that pass a test
const evenNumbers = numbers.filter(num => num % 2 === 0);
console.log(evenNumbers);  // [2, 4]

// reduce - reduces the array to a single value
const sum = numbers.reduce((total, num) => total + num, 0);
console.log(sum);  // 15

// find - returns the first element that passes a test
const found = numbers.find(num => num > 3);
console.log(found);  // 4

// findIndex - returns the index of the first element that passes a test
const foundIndex = numbers.findIndex(num => num > 3);
console.log(foundIndex);  // 3

// some - checks if at least one element passes a test
const hasEven = numbers.some(num => num % 2 === 0);
console.log(hasEven);  // true

// every - checks if all elements pass a test
const allPositive = numbers.every(num => num > 0);
console.log(allPositive);  // true

// includes - checks if an array contains a specific element
console.log(numbers.includes(3));  // true
console.log(numbers.includes(6));  // false

// join - joins all elements into a string
console.log(numbers.join(", "));  // "1, 2, 3, 4, 5"

// slice - returns a portion of an array
const sliced = numbers.slice(1, 4);
console.log(sliced);  // [2, 3, 4]

Array Destructuring (ES6)

const rgb = [255, 128, 64];

// Basic destructuring
const [red, green, blue] = rgb;
console.log(red);    // 255
console.log(green);  // 128
console.log(blue);   // 64

// Skipping elements
const [first, , third] = rgb;
console.log(first);  // 255
console.log(third);  // 64

// Rest pattern
const [head, ...tail] = [1, 2, 3, 4, 5];
console.log(head);  // 1
console.log(tail);  // [2, 3, 4, 5]

// Default values
const [a, b, c, d = 0] = [1, 2, 3];
console.log(d);  // 0 (default value)

// Swapping variables
let x = 1;
let y = 2;
[x, y] = [y, x];
console.log(x);  // 2
console.log(y);  // 1

Spread Operator with Arrays

// Copying arrays
const original = [1, 2, 3];
const copy = [...original];
console.log(copy);  // [1, 2, 3]

// Merging arrays
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const merged = [...arr1, ...arr2];
console.log(merged);  // [1, 2, 3, 4, 5, 6]

// Creating a new array with additional elements
const expanded = [...arr1, 7, 8, 9];
console.log(expanded);  // [1, 2, 3, 7, 8, 9]

// Using spread with functions
function sum(a, b, c) {
  return a + b + c;
}

const numbers = [1, 2, 3];
console.log(sum(...numbers));  // 6

Working with JSON

JSON (JavaScript Object Notation) is a lightweight data interchange format that is easy for humans to read and write and easy for machines to parse and generate.

// Converting JavaScript objects to JSON strings
const person = {
  name: "John",
  age: 30,
  isEmployed: true,
  skills: ["JavaScript", "HTML", "CSS"]
};

const jsonString = JSON.stringify(person);
console.log(jsonString);
// {"name":"John","age":30,"isEmployed":true,"skills":["JavaScript","HTML","CSS"]}

// Pretty-printing JSON
const prettyJson = JSON.stringify(person, null, 2);
console.log(prettyJson);
// {
//   "name": "John",
//   "age": 30,
//   "isEmployed": true,
//   "skills": [
//     "JavaScript",
//     "HTML",
//     "CSS"
//   ]
// }

// Converting JSON strings back to JavaScript objects
const jsonData = '{"name":"Jane","age":25,"isEmployed":false}';
const parsedData = JSON.parse(jsonData);
console.log(parsedData.name);  // "Jane"
console.log(parsedData.age);   // 25

Interactive Example: Object Explorer

Best Practices for Objects and Arrays

  • Use Object Literals: Prefer object literals over the new Object() syntax.
  • Use Array Literals: Prefer array literals over the new Array() syntax.
  • Use Destructuring: Use object and array destructuring for cleaner code.
  • Use Spread Operator: Use the spread operator for copying and merging objects and arrays.
  • Immutability: Treat objects and arrays as immutable when possible, creating new copies instead of modifying existing ones.
  • Use Array Methods: Prefer array methods like map, filter, and reduce over traditional loops for cleaner, more functional code.
  • Property Shorthand: Use property shorthand when the property name matches the variable name.
  • Method Shorthand: Use method shorthand in object literals.
  • Computed Property Names: Use computed property names when property names are dynamic.

Next Steps

Now that you understand JavaScript objects and arrays, you can explore:

  • Prototypes and inheritance
  • Classes in JavaScript (ES6+)
  • Advanced array manipulation techniques
  • Working with complex data structures
  • Map and Set objects