Platinum Partner
java

Dependency-Injection and JavaScript Closures

As you can tell I am a big fan of DI, but I kept hearing that DI is not needed with dynamic languages, so after using JS for many months I am happy to say that DI is important there as well. In other words dependency managment and controll matters. But it is different.

Say you have a class for greeting with DI.

class Greeter {
String greeting;
Greeter(String greeting) {
this.greeting = greeting;
}
void greet(String name) {
System.out.println(this.greeting + name);
}
}

Since the class only has one responsibility it only has one method. Now we can rewrite this in JavaScript in OO way like this:

function Greeter(greeting) {
this.greeting = greeting;
}
Greeting.prototype.greet = function(name){
alert(this.greeting + name);
};

While this code is fine, it does not follow the spirit of JavaScript which is a functional language. Why have a Greeter noun when you can just have greet verb. (see: Execution in the kingdom of nouns) So let’s rewrite it in functional style:

function greetFactory(greeting) {
return function(name) {
alert(greeting + name);
};
}

so usage changes from:

var greeter = new Greeter('Hello ');
greeter.greet('misko');

to:

var greet = greetFactory('Hello ');
greet('Misko');

Notice that in all cases the DI of greeting is preserved just fine. Now here comes an interesting thing. Objects have scopes. For example the alert method in JavaScript (or System.out.println method in Java) needs to be DI as well since we want to verify that the right thing is printed in test. But the alert method needs to be injected not just into our function but most likely into hundreds of other functions in our application. It is kind of a singleton. So in java we have to do this:

class Greeter {
String greeting;
OutputStream out;
Greeter(OutputStream out, String greeting) {
this.out = out;
this.greeting = greeting;
}

void greet(String name) {
out.println(this.greeting + name);
}
}

The JavaScript equivalent would be:

function greetFactory(alert, greeting) {
return function(name) {
alert(greeting + name);
};
}

But that means that we are no better than Java in injecting the same thing everywhere. The trick is in realizing that object injection is nested in scopes, and that every factory which needs alert share the same alert so we can rewrite this like this;

function createFactories(alert) {
return {
greetFactory: function(greeting) {
return function(greet) {
alert(greeting + greet);
};
},
someOtherFactory: function(...) {
return function(...){ alert(...); };
}
};
}

When you are ready to bootstrap your app you can:

var factories = createFactories(myAlert);
var greet = factories.createGreet('Hello ');
greet('Misko');

From http://misko.hevery.com/2010/05/29/dependency-injection-and-javascript-closures

{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks
Tweet

{{parent.nComments}}