Javascript
  • intro.
  • 1 - Getting started
  • 2 - Basics
  • 3 - Functions and Scope
  • 4 - Advanced Concepts
  • 5 - JavaScript in the Browser
  • 6 - JavaScript and Browser Storage
  • 7 - Asynchronous JavaScript
  • 8 - Design Patterns
  • 9 - Frameworks Overview
  • 10 - Testing and Debugging
Powered by GitBook
On this page
  • Closures in Depth
  • What are Closures?
  • Use Cases of Closures
  • Higher-Order Functions
  • What are Higher-Order Functions?
  • Common Higher-Order Functions
  • The this Keyword in JavaScript
  • Understanding this
  • Prototypes and Inheritance
  • What is a Prototype?
  • Inheritance
  • Classes in JavaScript (ES6)
  • The Event Loop and Asynchronous JavaScript
  • The Event Loop
  • Asynchronous JavaScript

4 - Advanced Concepts

Closures in Depth

What are Closures?

  • Closures: Functions that can access variables from their enclosing scope, even after that scope has exited.

  • How They Work: Closures keep references to the outer scope variables alive, allowing you to use them later.

    • Example:

      function makeMultiplier(x) {
          return function(y) {
              return x * y;
          };
      }
      const multiplyBy3 = makeMultiplier(3);
      console.log(multiplyBy3(4));  // Output: 12
      console.log(multiplyBy3(5));  // Output: 15
    • Explanation: The inner function remembers x from the outer function, even after makeMultiplier has finished executing.

Use Cases of Closures

  • Data Privacy: Create private variables by encapsulating them within a function.

    • Example:

      function Counter() {
          let count = 0;
          return {
              increment: function() {
                  count++;
                  return count;
              },
              decrement: function() {
                  count--;
                  return count;
              }
          };
      }
      const counter = Counter();
      console.log(counter.increment());  // Output: 1
      console.log(counter.decrement());  // Output: 0
  • Event Handlers: Closures are often used in event listeners to retain access to external variables.

Higher-Order Functions

What are Higher-Order Functions?

  • Higher-Order Functions: Functions that either take other functions as arguments or return functions.

    • Examples include map(), filter(), and reduce().

    • Example:

      function applyOperation(a, b, operation) {
          return operation(a, b);
      }
      const sum = (x, y) => x + y;
      console.log(applyOperation(5, 3, sum));  // Output: 8

Common Higher-Order Functions

  • map(): Creates a new array by applying a function to each element of the original array.

    • Example:

      let numbers = [1, 2, 3, 4];
      let doubled = numbers.map(num => num * 2);
      console.log(doubled);  // Output: [2, 4, 6, 8]
  • filter(): Creates a new array with all elements that pass the test implemented by the provided function.

    • Example:

      let scores = [10, 15, 20, 25];
      let highScores = scores.filter(score => score > 15);
      console.log(highScores);  // Output: [20, 25]
  • reduce(): Executes a reducer function on each element of the array, resulting in a single output value.

    • Example:

      let sum = numbers.reduce((acc, current) => acc + current, 0);
      console.log(sum);  // Output: 10

The this Keyword in JavaScript

Understanding this

  • this: Refers to the object that is executing the current function.

    • In the global scope, this refers to the global object (window in browsers).

    • In an object method, this refers to the object the method is called on.

    • In arrow functions, this retains the value from the enclosing lexical context.

Examples of this

  • Global Scope:

    console.log(this);  // In browser: window object
  • Object Method:

    const person = {
        name: "Alice",
        greet: function() {
            console.log("Hello, " + this.name);
        }
    };
    person.greet();  // Output: "Hello, Alice"
  • Arrow Function:

    function LexicalExample() {
        this.value = 100;
        const showValue = () => {
            console.log(this.value);
        };
        showValue();  // Output: 100 (inherits `this` from LexicalExample)
    }
    new LexicalExample();

Prototypes and Inheritance

What is a Prototype?

  • Prototype: Every JavaScript object has a prototype, which is an object itself from which other objects inherit properties and methods.

    • Prototype Chain: Mechanism through which objects inherit from one another.

    • Example:

      function Person(name) {
          this.name = name;
      }
      Person.prototype.sayHello = function() {
          console.log("Hello, my name is " + this.name);
      };
      const john = new Person("John");
      john.sayHello();  // Output: "Hello, my name is John"

Inheritance

  • Inheritance: Mechanism for creating a new object based on an existing object.

    • Example using Prototypal Inheritance:

      const animal = {
          speak() {
              console.log("Animal sound");
          }
      };
      const dog = Object.create(animal);
      dog.bark = function() {
          console.log("Woof!");
      };
      dog.speak();  // Output: "Animal sound"
      dog.bark();   // Output: "Woof!"

Classes in JavaScript (ES6)

  • Classes: A syntactic sugar for creating objects and dealing with inheritance in JavaScript.

    • Syntax:

      class Car {
          constructor(brand) {
              this.brand = brand;
          }
          start() {
              console.log(this.brand + " is starting");
          }
      }
      const myCar = new Car("Toyota");
      myCar.start();  // Output: "Toyota is starting"

The Event Loop and Asynchronous JavaScript

The Event Loop

  • Event Loop: Handles asynchronous operations by continuously checking the call stack and the task queue.

    • How It Works:

      • The call stack handles function execution.

      • The task queue (or callback queue) holds callback functions waiting to be executed.

      • Example:

        console.log("Start");
        setTimeout(() => {
            console.log("Callback");
        }, 1000);
        console.log("End");
        // Output: "Start", "End", "Callback"

Asynchronous JavaScript

  • Callbacks: Functions passed as arguments to other functions, often used to handle asynchronous code.

    • Example:

      function fetchData(callback) {
          setTimeout(() => {
              callback("Data received");
          }, 1000);
      }
      fetchData(data => {
          console.log(data);  // Output: "Data received"
      });
  • Promises: Objects representing a value that may be available now, or in the future, or never.

    • Example:

      const promise = new Promise((resolve, reject) => {
          let success = true;
          if (success) {
              resolve("Promise fulfilled");
          } else {
              reject("Promise rejected");
          }
      });
      promise.then(result => console.log(result)).catch(error => console.log(error));
  • Async/Await: Syntactic sugar to work with promises in a more readable manner.

    • Example:

      async function asyncFunction() {
          try {
              let result = await promise;
              console.log(result);  // Output: "Promise fulfilled"
          } catch (error) {
              console.error(error);
          }
      }
      asyncFunction();

Summary

  • Closures: Essential for retaining access to the scope of an outer function, allowing for data privacy and function factories.

  • Higher-Order Functions: Functions like map(), filter(), and reduce() that accept or return other functions.

  • this Keyword: Understand how this behaves differently in various contexts, especially with arrow functions.

  • Prototypes and Inheritance: The fundamental mechanism for object inheritance in JavaScript.

  • Event Loop: Understand how JavaScript handles asynchronous code using the event loop.


Next Chapter: JavaScript in the Browser

Previous3 - Functions and ScopeNext5 - JavaScript in the Browser

Last updated 6 months ago