Dependency Injection in Javascript

This is the first step in an Dependency Injection Framework in Javascript:

Now updated to show passing on the registry.

This still needs work.  It is OK for the Registry to be a global, but the resolution of an component should be scoped….Like I said, a first step.

#!/usr/bin/rhino

var Registry = {

    factories : {},
    instances : {},

    register:  function(name,factory){

        this.factories[name] = factory;

        this.__defineGetter__(name, function() {

            if (!this.instances[name]){
                this.instances[name] = this.factories[name](this);
            }

            return this.instances[name];
        });
    }
}

Registry.register("teststring",function(){
    return "Injected";
});

Registry.register("testobj",function(registry){
    var that = {};
    that.string = registry.teststring;
    that.execute = function(){
        print(that.string);
    }
    return that;
});

Registry.testobj.execute();

Updated: This version would keep a separate instance variable per “request”

#!/usr/bin/rhino

var Registry = {

    factories : {},
    keys: [],
    register:  function(name,factory){
        this.factories[name] = factory;
        this.keys.push(name);
    },

    define_getter: function(scope,key){
        var facts = this.factories;
        scope.__defineGetter__(key, function() {
            var x = key;
            if (!scope.instances[x]){
                scope.instances[x] = facts[x](scope);
            }
            return scope.instances[key];
        });
    },

    request_scope: function(){
        var scope = {};
        scope.instances = {};
        var facts = this.factories;
        for (var i = 0; i < this.keys.length; i +=1){
            this.define_getter(scope,this.keys[i]);
        }
        return scope;
    }
}


Registry.register("teststring",function(scope){
    return "Injected";
});

Registry.register("testobj",function(scope){
    var that = {};
    that.string = scope.teststring;
    that.execute = function(){
        print("executing " + that.string);
    }
    return that;
});


var scope =  Registry.request_scope();

var test_string = scope.teststring;
var test_obj = scope.testobj;
test_obj.execute();


6 thoughts on “Dependency Injection in Javascript

  1. Interesting. Just getting into node.js for CQRS backed by NoSQL (RavenDB) and was wondering about DI and whether js really needed DI. Doubly so as a coding, Vietnam vet, ex-NH rock climber, and Peregrine monitor out here in Oregon.

  2. I’d say that DI is a good approach for coding in general, and Javascript code would benefit from it. The general rule is “Separate construction from usage.” which really is just a good practice.

    Been a while since I’ve been to Smith Rock.

  3. Your codes are so elegant.

    I have a question that why updated to the version which keep a separate instance variable per “request”. When do I need two scope like that:

    var scope1 = Registry.request_scope();
    // scope1 do something
    var scope2 = Registry.request_scope();
    // scope2 do something

    Is there a project for this like “CppInject”?

    Thanks.

  4. Coordinate

    You wouldn’t do that in the same function call. Instead, in each request, you create a separate instance of the request scope resolver *per* request. It is possible that two requests can come in simultaneously, and they should resolve instances to the appropriate responses, not get crossed.

    I wrote similar code for C++ here.

    http://adam.younglogic.com/2008/07/dependency-injection-in-c/

    Code is on Git Hub, link at the bottom.

  5. I’d argue that it implements the Dependency Locator in order to perform dependency injection. They are very related patterns.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.