Creating Template Functions with Closure

Modified on Tue, 2 Jul at 10:22 AM

Often, differing requirements in output lead us to create separate functions that achieve similar results, with slight differences in behavior. Consider these functions that take the scores of 3 students in a class and print “pass” or “fail” depending on the score, along with their names:

function student1(score) {
  if (score >= 50) {
    console.log("Student 1: Pass");
  } else {
    console.log("Student 1: Fail");
  }
}



function student2(score) {
  if (score >= 50) {
    console.log("Student 2: Pass");
  } else {
    console.log("Student 2: Fail");
  }
}



function student3(score) {
  if (score >= 50) {
    console.log("Student 3: Pass");
  } else {
    console.log("Student 3: Fail");
  }
}


In scenarios where minor adjustments in the common behavior of the above functions are needed, you would have to change multiple lines of code (imagine not 3 but 300 students!). This is where closures help us create simple and readable functions that can be easily modified.

Closures allow us to create templated functions, similar to a function generator. This outer function, when called, will return the inner function which behaves according to the environment of the outer function.

function createStudentFunction(studentName) {
  return function(score) {
    if (score >= 50) {
      console.log(`${studentName}: Pass`);
    } else {
      console.log(`${studentName}: Fail`);
    }
  };
}

const student1 = createStudentFunction("Student 1");
const student2 = createStudentFunction("Student 2");
const student3 = createStudentFunction("Student 3");

student1(55); // Student 1: Pass
student2(45); // Student 2: Fail
student3(70); // Student 3: Pass


Here, studentName is a variable declared within the outer function environment, but the inner function, which is returned, will remember this variable. The inner function will take the variable score and calculate the result for the student.

Back to the original use case - minor adjustments in the behavior of the function. Suppose we want to change the phrase “Fail” to “Fell Short”. Which code is more preferred?

  1. Changing the phrase in 3 different functions:

function student1(score) {
  if (score >= 50) {
    console.log("Student 1: Pass");
  } else {
    console.log("Student 1: Fell Short");
  }
}

function student2(score) {
  if (score >= 50) {
    console.log("Student 2: Pass");
  } else {
    console.log("Student 2: Fell Short");
  }
}

function student3(score) {
  if (score >= 50) {
    console.log("Student 3: Pass");
  } else {
    console.log("Student 3: Fell Short");
  }
}


  1. Using closures to make the adjustment:

function createStudentFunction(studentName) {
  return function(score) {
    if (score >= 50) {
      console.log(`${studentName}: Pass`);
    } else {
      console.log(`${studentName}: Fell Short`);
    }
  };
}

const student1 = createStudentFunction("Student 1");
const student2 = createStudentFunction("Student 2");
const student3 = createStudentFunction("Student 3");

student1(55); // Student 1: Pass
student2(45); // Student 2: Fell Short
student3(70); // Student 3: Pass


Clearly, the second method is easier and more readable.

Moreover, it is critical to remember why:

  • We passed the name to the outer function: The name of the student, or studentName, is the parameter that will modify the behavior of the inner function.

  • We passed the score to the inner function: score is the parameter that will be used by the inner function to produce the end result.

Here are some of the problems where this concepts are used:

Was this article helpful?

That’s Great!

Thank you for your feedback

Sorry! We couldn't be helpful

Thank you for your feedback

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article