Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Dependency-Injection and JavaScript Closures

DZone's Guide to

Dependency-Injection and JavaScript Closures

· Java Zone
Free Resource

The single app analytics solutions to take your web and mobile apps to the next level.  Try today!  Brought to you in partnership with CA Technologies

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

CA App Experience Analytics, a whole new level of visibility. Learn more. Brought to you in partnership with CA Technologies.

Topics:

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

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

{{ parent.tldr }}

{{ parent.urlSource.name }}