Advanced JavaScript Concepts

Introduction

JavaScript is a popular programming language used for web development. Among its many features are advanced concepts that make it a versatile language. In this article, we will explore these concepts, including array methods, closures, classes, promises, and generators.

Array Methods

JavaScript arrays are versatile data structures that can hold any type of data, including other arrays and objects. They also offer several built-in methods for manipulating data. Here are four advanced array methods you should know:

map

The map method creates a new array with the results of calling a provided function on every element in the calling array. This method does not modify the original array.

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

filter

The filter method creates a new array with all elements that pass the test implemented by the provided function. This method does not modify the original array.

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

reduce

The reduce method applies a function against an accumulator and each element in the array to reduce it to a single value. This method does not modify the original array.

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

forEach

The forEach method executes a provided function once for each array element. This method does not create a new array and does not modify the original array.

const numbers = [1, 2, 3, 4];
numbers.forEach(number => console.log(number * 2)); // 2, 4, 6, 8

Closures

A closure is a function that has access to variables in its outer (enclosing) function’s scope chain, even after the outer function has returned.

const outerFunction = () => {
  const outerVariable = 'outer variable';

  const innerFunction = () => {
    console.log(outerVariable);
  };

  return innerFunction;
};

const innerFunction = outerFunction();
innerFunction(); // 'outer variable'

In the above example, innerFunction has access to the outerVariable, even though it is not directly declared inside the innerFunction.

Classes

JavaScript classes are a version of JavaScript’s prototypical inheritance. They provide a way to define complex objects with their own methods and properties, much like traditional object-oriented programming (OOP) languages.

Defining classes

class Dog {
  constructor(name, breed) {
    this.name = name;
    this.breed = breed;
  }

  bark() {
    console.log('Woof!');
  }

  displayInfo() {
    console.log(`Name: ${this.name}, Breed: ${this.breed}`);
  }
}

const myDog = new Dog('Rufus', 'Labrador');
myDog.displayInfo();
myDog.bark();

In the above example, we define a Dog class with a constructor function that takes a name and breed argument and sets them as properties of the new instance. We also define a bark method and a displayInfo method that logs information about the dog instance.

Extending classes

We can also extend existing classes to create new classes with added functionality.

class ServiceDog extends Dog {
  constructor(name, breed, serviceType) {
    super(name, breed);
    this.serviceType = serviceType;
  }

  performService() {
    console.log(`Performing ${this.serviceType} service.`);
  }
}

const myServiceDog = new ServiceDog('Lacey', 'Golden Retriever', 'Therapy');
myServiceDog.displayInfo();
myServiceDog.bark();
myServiceDog.performService();

In the above example, we define a ServiceDog class that extends the Dog class. We use the super() method to call the Dog class constructor and add a serviceType property. We also define a performService method that is specific to the ServiceDog class.

Promises

Promises are objects that represent the eventual completion (or failure) of an asynchronous operation and its resulting value. They provide an alternative to working with callbacks.

Creating promises

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Success!');
  }, 1000);
});

In the above example, we define a myPromise object with a constructor function that takes a resolve and reject argument. We use the setTimeout() function to simulate an asynchronous operation that resolves after one second and returns the string 'Success!'.

Working with promises

myPromise
  .then(result => console.log(result))
  .catch(error => console.log(error));

In the above example, we use the .then() method to handle the resolved myPromise result and the .catch() method to handle any errors. This results in the string 'Success!' being logged to the console after one second.

Generators

Generators are functions that can be paused and resumed, allowing for the creation of iterators. They offer a powerful way to write asynchronous and concurrent code in a synchronous style.

Defining generators

function* myGenerator() {
  yield 1;
  yield 2;
  yield 3;
}

const generator = myGenerator();

console.log(generator.next().value); // 1
console.log(generator.next().value); // 2
console.log(generator.next().value); // 3

In the above example, we define a myGenerator function that uses the yield keyword to define a set of values to be returned by the generator. We create an instance of the generator and use the .next() method to iterate through the values.

Sending data to generators

function* myGenerator() {
  const greeting = yield;
  console.log(greeting);
}

const generator = myGenerator();

generator.next();
generator.next('Hello!'); // 'Hello!'

In the above example, we define a myGenerator function that assigns a greeting variable to the value passed to the generator using the yield keyword. We create an instance of the generator and use the .next() method to start it and send the value 'Hello!' to the generator.

Conclusion

In this article, we explored several advanced JavaScript concepts, including array methods, closures, classes, promises, and generators. These concepts provide powerful ways to manipulate and work with data, as well as write asynchronous and concurrent code. Keep exploring these concepts and you’ll be on your way to mastering JavaScript!

Related Post