JavaScript
Objects and Array

Understanding Objects and Array

Objects and Arrays

Objects and Arrays are fundamental data structures in JavaScript used to store collections of data.

Object Manipulation

  1. Creation Using Literal Notation:

    // Object literal notation
    const person = {
      name: 'John Doe',
      age: 30,
      greet() {
        return `Hello, my name is ${this.name}.`;
      }
    };
     
    console.log(person.name); // 'John Doe'
    console.log(person.greet()); // 'Hello, my name is John Doe.'

    Explanation: This creates an object person with properties name and age, and a method greet.

  2. Creation Using Constructors:

    // Constructor function
    function Person(name, age) {
      this.name = name;
      this.age = age;
    }
     
    Person.prototype.greet = function() {
      return `Hello, my name is ${this.name}.`;
    };
     
    const john = new Person('John Doe', 30);
     
    console.log(john.name); // 'John Doe'
    console.log(john.greet()); // 'Hello, my name is John Doe.'

    Explanation: The Person function is a constructor for creating new Person objects with name and age properties and a greet method.

  3. Creation Using Object.create():

    // Prototype-based creation
    const personPrototype = {
      greet() {
        return `Hello, my name is ${this.name}.`;
      }
    };
     
    const john = Object.create(personPrototype);
    john.name = 'John Doe';
    john.age = 30;
     
    console.log(john.name); // 'John Doe'
    console.log(john.greet()); // 'Hello, my name is John Doe.'

    Explanation: Object.create() creates an object with the specified prototype object (personPrototype). Properties can then be added to the new object.

Array Methods

  1. push():

    const fruits = ['apple', 'banana'];
    fruits.push('cherry');
     
    console.log(fruits); // ['apple', 'banana', 'cherry']

    Explanation: Adds a new element ('cherry') to the end of the fruits array.

  2. pop():

    const fruits = ['apple', 'banana', 'cherry'];
    const lastFruit = fruits.pop();
     
    console.log(lastFruit); // 'cherry'
    console.log(fruits); // ['apple', 'banana']

    Explanation: Removes the last element ('cherry') from the fruits array and returns it.

  3. map():

    const numbers = [1, 2, 3];
    const doubled = numbers.map(num => num * 2);
     
    console.log(doubled); // [2, 4, 6]

    Explanation: Creates a new array where each element is the result of applying the provided function to each element in the numbers array.

  4. filter():

    const numbers = [1, 2, 3, 4, 5];
    const evenNumbers = numbers.filter(num => num % 2 === 0);
     
    console.log(evenNumbers); // [2, 4]

    Explanation: Creates a new array containing only the elements that satisfy the provided condition (even numbers in this case).

  5. reduce():

    const numbers = [1, 2, 3, 4];
    const sum = numbers.reduce((accumulator, current) => accumulator + current, 0);
     
    console.log(sum); // 10

    Explanation: Reduces the array to a single value by applying a function (summing in this case) to each element.

Destructuring

Arrays:

const numbers = [1, 2, 3];
const [a, b, c] = numbers;
 
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3

Objects:

const person = { name: 'John', age: 30 };
const { name, age } = person;
 
console.log(name); // 'John'
console.log(age); // 30

Explanation: Destructuring allows for extracting values from arrays or objects into separate variables in a concise manner.

Flattening Arrays

  1. Using flat():

    const nestedArray = [1, [2, [3, [4]]]];
    const flatArray = nestedArray.flat(2);
     
    console.log(flatArray); // [1, 2, 3, [4]]

    Explanation: The flat() method flattens nested arrays up to a specified depth (2 in this case).

  2. Using Recursion:

    function flattenArray(arr) {
      return arr.reduce((flat, toFlatten) => 
        flat.concat(Array.isArray(toFlatten) ? flattenArray(toFlatten) : toFlatten), []);
    }
     
    const nestedArray = [1, [2, [3, [4]]]];
    console.log(flattenArray(nestedArray)); // [1, 2, 3, 4]

    Explanation: The flattenArray function recursively concatenates elements, flattening nested arrays.

Flatten Object

function flattenObject(obj, prefix = '') {
  let items = [];
  for (const [key, value] of Object.entries(obj)) {
    const newKey = prefix ? `${prefix}.${key}` : key;
    if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
      items = items.concat(flattenObject(value, newKey));
    } else {
      items.push([newKey, value]);
    }
  }
  return Object.fromEntries(items);
}
 
const nestedObj = { a: 1, b: { c: 2, d: { e: 3 } } };
console.log(flattenObject(nestedObj)); // { a: 1, 'b.c': 2, 'b.d.e': 3 }

Explanation: The flattenObject function flattens nested objects by concatenating nested keys into a single level object.

Cloning Arrays

  1. Using slice():

    const original = [1, 2, 3];
    const clone = original.slice();
     
    console.log(clone); // [1, 2, 3]

    Explanation: slice() creates a shallow copy of the array.

  2. Using Spread Operator (...):

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

    Explanation: The spread operator (...) creates a shallow copy of the array.

  3. Using Array.from():

    const original = [1, 2, 3];
    const clone = Array.from(original);
     
    console.log(clone); // [1, 2, 3]

    Explanation: Array.from() creates a shallow copy of the array.

Cloning Objects

  1. Using Object.assign():

    const original = { a: 1, b: 2 };
    const clone = Object.assign({}, original);
     
    console.log(clone); // { a: 1, b: 2 }

    Explanation: Object.assign() creates a shallow copy of the object.

  2. Using Spread Operator (...):

    const original = { a: 1, b: 2 };
    const clone = { ...original };
     
    console.log(clone); // { a: 1, b: 2 }

    Explanation: The spread operator (...) creates a shallow copy of the object.

  3. Deep Cloning with Libraries (e.g., Lodash):

    const _ = require('lodash');
     
    const original = { a: 1, b: { c: 2 } };
    const clone = _.cloneDeep(original);
     
    console.log(clone); // { a: 1, b: { c: 2 } }

    Explanation: _.cloneDeep() creates a deep copy of the object, including nested properties.

  4. Deep Cloning with Custom Recursive Method:

    function deepClone(obj) {
      if (obj === null || typeof obj !== 'object') return obj;
     
      const copy = Array.isArray(obj) ? [] : {};
     
      for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
          copy[key] = deepClone(obj[key]);
        }
      }
      return copy;
    }
     
    const original = { a: 1, b: { c: 2 } };
    const clone = deepClone(original);
     
    console.log(clone); // { a: 1, b: { c: 2 } }

    Explanation: The deepClone function recursively copies properties to ensure a deep clone.

Merging Arrays and Objects

  1. Merging Arrays:

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

    Explanation: Using the spread operator (...) merges multiple arrays into one.

  2. Merging Objects:

    const obj1 = { a: 1, b: 2 };
    const obj2 = { b: 3, c: 4 };
    const merged = { ...obj1, ...obj2 };
     
    console.log(merged); // { a: 1, b: 3, c: 4 }

    Explanation: The spread operator (...) merges objects, with later properties overwriting earlier ones.

Removing Duplicates

  1. Using Set:

    const numbers = [1, 2, 2, 3, 4, 4];
    const unique = [...new Set(numbers)];
     
    console.log(unique); // [1, 2, 3, 4]

    Explanation: Set automatically removes duplicate values, and the spread operator (...) converts it back to an array.

  2. Using filter():

    const numbers = [1, 2, 2, 3, 4, 4];
    const unique = numbers.filter((value, index, self) => self.indexOf(value) === index);
     
    console.log(unique); // [1, 2, 3, 4]

    Explanation: filter() keeps only the first occurrence of each value.

  3. Using Custom Logic:

    function removeDuplicates(arr) {
      const seen = {};
      return arr.filter(item => {
        return seen.hasOwnProperty(item) ? false : (seen[item] = true);
      });
    }
     
    const numbers = [1, 2, 2, 3, 4, 4];
    console.log(removeDuplicates(numbers)); // [1, 2, 3, 4]

    Explanation: This custom function uses an object to track seen values and filter out duplicates.

By understanding these techniques and their applications, you can handle complex data structures more effectively in JavaScript.