DEV Community

francesco agati
francesco agati

Posted on

Closures, Higher-Order Functions, and Prototypal Inheritance in JavaScript

JavaScript is a versatile language that mix functional programming and object-oriented programming paradigms. This flexibility allows developers to create powerful abstractions. We can try to mix concepts such as closures, higher-order functions, prototypal inheritance, and the this keyword to create elegant solutions.

Closures

A closure is a function that retains access to its lexical scope, even when the function is executed outside that scope. This means a closure "remembers" the environment in which it was created.

Example:

function outerFunction(outerVariable) {
  return function innerFunction(innerVariable) {
    console.log('Outer Variable:', outerVariable);
    console.log('Inner Variable:', innerVariable);
  };
}

const newFunction = outerFunction('outside');
newFunction('inside'); // Outputs: Outer Variable: outside, Inner Variable: inside
Enter fullscreen mode Exit fullscreen mode

In this example, innerFunction forms a closure, capturing the outerVariable from its lexical scope.

Higher-Order Functions

A higher-order function is a function that either takes another function as an argument or returns a function as its result.

Example:

function higherOrderFunction(callback) {
  return function(value) {
    return callback(value);
  };
}

const addTen = higherOrderFunction(function(num) {
  return num + 10;
});

console.log(addTen(5)); // Outputs: 15
Enter fullscreen mode Exit fullscreen mode

Here, higherOrderFunction is a higher-order function that returns a new function applying the callback.

Prototypal Inheritance

JavaScript uses prototypal inheritance, where objects inherit properties and methods from other objects. This is achieved through the prototype chain.

Example:

function Animal(name) {
  this.name = name;
}

Animal.prototype.speak = function() {
  console.log(this.name + ' makes a noise.');
};

const dog = new Animal('Dog');
dog.speak(); // Outputs: Dog makes a noise.
Enter fullscreen mode Exit fullscreen mode

In this example, dog inherits the speak method from Animal.prototype.

The this Keyword

In JavaScript, this refers to the context in which a function is called. Its value can change depending on how the function is invoked.

Example:

const obj = {
  name: 'Object',
  getName: function() {
    return this.name;
  }
};

console.log(obj.getName()); // Outputs: Object
Enter fullscreen mode Exit fullscreen mode

Here, this refers to obj within getName method.

Combining Concepts: A Code Example

Now, let's combine these concepts in a practical example that uses closures, higher-order functions, prototypal inheritance, and dynamic this binding.

Example:

function multiplier(x) {
  return function(y) {
    return x * y * this.z;
  };
}

const mul5 = multiplier(5);

const Obj = function(z) {
  this.z = z;
};

Obj.prototype.mul5 = mul5;

const obj = new Obj(10);
console.log(obj.mul5(15)); // Outputs: 750
Enter fullscreen mode Exit fullscreen mode

Explanation:

  1. Closure and Higher-Order Function: The multiplier function returns another function, creating a closure that captures the value of x.
  2. Dynamic this Binding: The inner function returned by multiplier uses this.z. When mul5 is called as a method of obj, this refers to obj.
  3. Prototypal Inheritance: Obj is a constructor function, and mul5 is assigned to its prototype. This means every instance of Obj will have access to the mul5 method.

Functional and Prototype-Based Abstractions

Both functional programming (closures, higher-order functions) and prototype-based programming, can create powerful abstractions. Here are some benefits:

  • Modularity: Functions and methods can be easily reused and composed.
  • Encapsulation: Closures help in encapsulating private variables and functions.
  • Inheritance: Prototypal inheritance allows for shared methods and properties, reducing redundancy.

Combining functional programming techniques with JavaScript's prototypal inheritance system provides a robust way to write clean, maintainable, and efficient code. Understanding and utilizing closures, higher-order functions, dynamic this binding, and prototypes together can significantly enhance your programming toolkit, leading to elegant and powerful abstractions.

Top comments (1)

Collapse
 
jonrandy profile image
Jon Randy 🎖️ • Edited

A closure is a function that retains access to its lexical scope, even when the function is executed outside that scope. This means a closure "remembers" the environment in which it was created

Almost right. Closures are not a special type of function - they're actually not functions at all. If the above definition were correct, then the words 'function' and 'closure' could be used interchangeably, as ALL functions have the capability you mention.