Good morning! Here's our prompt for today.
In JavaScript, closures and dependency injection are powerful concepts that enable modular, maintainable, and flexible code. In this challenge, you will explore these concepts by implementing a specific functionality using closures and then using closures for dependency injection.
Part 1: Closures
Closures allow a function to access variables from an outer function that has already finished its execution. Your task is to create a closure that serves as a decrementing counter.
Boilerplate code:
1var minus = (function () {
2 // TODO: Initialize a counter variable
3 // TODO: Return a function that decrements the counter and returns the current value
4})();
Part 2: Dependency Injection with Closures
Dependency Injection is a technique where one object supplies the dependencies of another object. You will create a function that returns factories for sending email and SMS messages, and these factories will use a logger function passed as a dependency.
Boilerplate code:
1function createFactories(logger) {
2 // TODO: Return an object containing emailFactory and smsFactory
3 // emailFactory should take a greeting and return a function that takes a greet and logs it using the logger
4 // smsFactory should take a text and return a function that logs the text using the logger
5}
Try to solve this here or in Interactive Mode.
How do I practice this challenge?
xxxxxxxxxx
package main
import "fmt"
func closuresAndDependencyInjection(arg string) string {
// fill in
return "output"
}
func main() {
// write test cases
fmt.Println(closuresAndDependencyInjection("input"))
}
Here's how we would solve this problem...
How do I use this guide?
Step 1: Understand the Problem
The challenge is to create a decrementing counter using closures, which means we need to create a function that returns another function. The inner function should have access to a variable from the outer function, and this variable will serve as our counter.

Step 2: Boilerplate Code Analysis
The given boilerplate code provides a starting point:
1var minus = (function () {
2 // TODO: Initialize a counter variable
3 // TODO: Return a function that decrements the counter and returns the current value
4})();
Here, we see an Immediately Invoked Function Expression (IIFE) that needs to initialize a counter variable and return a function that decrements this counter.
Step 3: Initialize the Counter Variable
First, we need to define a variable inside the IIFE that will act as our counter. This variable will be private, accessible only within the closure.
1var counter = 999;
Step 4: Create the Inner Function
Next, we need to create an inner function that has access to the counter
variable. This function will decrement the counter by 1 each time it is called.
1return function () {counter -= 1; return counter}
Step 5: Putting It Together
Combining Steps 3 and 4, we obtain the final code for the closure:
1var minus = (function () {
2 var counter = 999; // Initialize a counter variable
3 return function () {counter -= 1; return counter} // Return a function that decrements the counter
4})();
Step 6: Testing the Code
We can now test our code by calling the minus
function multiple times:
1minus(); // 998
2minus(); // 997
3minus(); // 996
The counter is successfully decremented each time the function is called, demonstrating that our closure is working as intended.
Understanding the Solution
- The outer function creates a scope where the
counter
variable is defined, encapsulating it and making it private. - The inner function is returned from the outer function and assigned to the variable
minus
. It maintains access to thecounter
variable. - Each call to
minus
decrements the counter, and the value is preserved between calls thanks to the closure.
xxxxxxxxxx
var minus = (function () {
var counter = 999;
return function () {counter -= 1; return counter}
})();
minus();
minus();
minus();
// 996
The self invoking function assigned to minus
only executes once, and creates a parent scope that returns a function expression. This function expression counter -= 1; return counter
has access to the counter from the parent scope, and abstracts it away from the global scope.
Let's move onto this next bit.
Step 1: Understand Dependency Injection
Dependency Injection (DI) is a design pattern where an object's dependencies are provided from outside rather than being created within the object. It increases modularity and allows for easier testing and reconfiguration. In this challenge, we will implement DI using closures to inject a logging function into different factories.

Hence the term-- such dependencies are injected into the object via the constructor or via defined method or a setter property.
This pattern decreases coupling between an object and its dependency, and allows reconfiguration without changing existing business logic. On the flip side, you're locked into certain dependency types and the dependency resolving logic might be abstracted away.
It is another way to using use dependencies from the global context.
We can apply dependency injection using closures. Let's say we had a certain logger we wanted to use, that we needed as a dependency to many factories.
Step 2: Analyzing the Boilerplate Code
The given boilerplate code lays out the structure of the problem:
1function createFactories(logger) {
2 // TODO: Return an object containing emailFactory and smsFactory
3 // emailFactory should take a greeting and return a function that takes a greet and logs it using the logger
4 // smsFactory should take a text and return a function that logs the text using the logger
5}
Here, we need to create a function createFactories
that accepts a logger
function and returns an object containing two factories, emailFactory
and smsFactory
.
Step 3: Creating the emailFactory
The emailFactory
takes a greeting and returns a function that takes a greet. This inner function will use the logger to log the concatenated greeting and greet.
1emailFactory: function(greeting) {
2 return function(greet) {
3 logger(greeting + greet);
4 };
5}
Step 4: Creating the smsFactory
Similarly, the smsFactory
will take some text and return a function that logs the text using the logger.
1smsFactory: function(text) {
2 return function(text) { logger(text); };
3}
Step 5: Combining emailFactory and smsFactory
We need to combine both factories inside the createFactories
function and return them as an object:
1function createFactories(logger) {
2 return {
3 emailFactory: function(greeting) {
4 return function(greet) {
5 logger(greeting + greet);
6 };
7 },
8 smsFactory: function(text) {
9 return function(text){ logger(text); };
10 }
11 };
12}
Step 6: Understanding the Solution
- The
createFactories
function accepts alogger
function as a dependency. - It returns an object containing two factories,
emailFactory
andsmsFactory
, both utilizing thelogger
. - The returned factories are closures that have access to the
logger
, allowing them to log messages in different ways. - By injecting the logger dependency, the code remains flexible and decoupled, allowing different loggers to be used without modifying the factory functions.
This exercise demonstrates how closures can be used to implement Dependency Injection in JavaScript. By building the solution step by step, we created a flexible and modular design where dependencies are injected from outside, enhancing maintainability and testability. The approach aligns with modern best practices in software design, showcasing the power and versatility of closures in managing dependencies.
xxxxxxxxxx
function createFactories(logger) {
return {
emailFactory: function(greeting) {
return function(greet) {
logger(greeting + greet);
};
},
smsFactory: function( ) {
return function( ){ logger( ); };
}
};
}
The two child methods returned have access to the scope created by createFactories
, and thus the logger
that was passed in. It enables the logger
to be encapsulated within createFactories
' scope, which will remain after the function has been executed. However, we'll still have access to the logger reference through emailFactory
and smsFactory
.
Combining Closures and Dependency Injection

We'll create a factory function that accepts a logger and a starting value for a counter. It will return an object containing a decrementing counter function (minus
) and a logging factory (createFactories
), demonstrating both closures and dependency injection.
- The
CounterAndLoggerFactory
function encapsulates both a decrementing counter (using a closure) and a set of factories that use a logger (demonstrating dependency injection). - The
counter
variable is private and can only be accessed through theminus
function. - The
createFactories
function returns two factory functions that utilize the injectedlogger
. - The returned object allows access to both the
minus
function and thecreateFactories
function, enabling both decrementing counter functionality and logging functionality.
By combining closures and dependency injection in this way, the code snippet showcases the versatility and power of these concepts in JavaScript, allowing for modular, maintainable, and flexible design.
Complexity of Final Solution
O(1)
constant time & space complexity, this is a knowledge question!
xxxxxxxxxx
emailSender("John!"); // Logs: Hello, John!
function CounterAndLoggerFactory(startValue, logger) {
var counter = startValue;
var minus = function () {
counter -= 1;
return counter;
};
function createFactories() {
return {
emailFactory: function(greeting) {
return function(greet) {
logger(greeting + greet);
};
},
smsFactory: function(text) {
return function(text) { logger(text); };
}
};
}
return {
minus: minus,
createFactories: createFactories
};
}
// Usage Example:
var logger = console.log;
One Pager Cheat Sheet
- A
closure
inJavascript
is a feature that can be used to implementdependency injection
, where a function can bepassed in
to access certain variables or methods. - A closure is a combination of a function and a lexical environment in which it was declared, allowing the function to access its
lexical environment
even from outside of the outer function. - Dependency injection with closures can be used to reduce coupling between an object and its dependency, while allowing reconfiguration without changing existing business logic, as an alternative to using global context dependencies.
- The
logger
remains encapsulated within the scope ofcreateFactories
and is accessible through the two returned child methods,emailFactory
andsmsFactory
, all inO(1)
constant time and space complexity.
This is our final solution.
To visualize the solution and step through the below code, click Visualize the Solution on the right-side menu or the VISUALIZE button in Interactive Mode.
xxxxxxxxxx
package main
import "fmt"
func closuresAndDependencyInjection(arg string) string {
// fill in
return "output"
}
func main() {
// write test cases
fmt.Println(closuresAndDependencyInjection("input"))
}
Great job getting through this. Let's move on.
If you had any problems with this tutorial, check out the main forum thread here.