Discover Functional JavaScript was named one of the best new Functional Programming books by BookAuthority!

Method decorators are a tool for reusing common logic. They are complementary to Object Oriented Programming. Decorators encapsulate responsibility shared by different objects.

Consider the following code:

function TodoStore(currentUser){
  let todos = [];
  
  function add(todo){
    let start = Date.now();
    if(currentUser.isAuthenticated()){
      todos.push(todo);
    } else {
      throw "Not authorized to perform this operation";
    }
            
    let duration = Date.now() - start;
    console.log("add() duration : " + duration);
  }
    
  return Object.freeze({
    add
  });  
}

The intent of the add() method is to add new to-dos to the internal state. Beside that, the method needs to check the user authorization and log the duration of execution. These two things are secondary concerns and can actually repeat in other methods.

Imagine we can encapsulate these secondary responsibilities in functions. Then we can write the code in the following way:

function TodoStore(){
  let todos = [];
  
  function add(todo){
    todos.push(todo);
  }
    
  return Object.freeze({
     add:compose(logDuration,authorize)(add) 
  }); 
}

Now the add() method just adds the todo to the list. The other responsibilities are implemented by decorating the method.

logDuration() and authorize() are decorators.

A function decorator is a higher-order function that takes one function as an argument and returns another function, and the returned function is a variation of the argument function.
Reginald Braithwaite in Javascript Allongé

Log Duration

A common scenario is logging the duration of a method call. The following decorator logs the duration of a synchronous call.

function logDuration(fn){
  return function decorator(...args){
    let start = Date.now();
    let result = fn.apply(this, args);
    let duration = Date.now() - start;
    console.log(fn.name + "() duration : " + duration);
    return result;
  }
}

Notice how the original function was called — by passing in the current value of this and all arguments : fn.apply(this, args) .

Discover Functional JavaScript was named one of the best new Functional Programming books by BookAuthority!

For more on applying functional programming techniques in React take a look at Functional React.

Learn functional React, in a project-based way, with Functional Architecture with React and Redux.

Follow on Twitter