Created
September 11, 2012 11:50
-
-
Save torgeir/3697840 to your computer and use it in GitHub Desktop.
Poor mans JavaScript dependency injection
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (function () { | |
| (typeof window == 'undefined' ? global : window).ioc = ioc; | |
| var singletons = {}; | |
| function ioc (Constructor, previous) { | |
| if ((previous || (previous = [])).indexOf(Constructor) != -1) { | |
| throw new Error('circular!'); | |
| } | |
| else { | |
| previous.push(Constructor); | |
| } | |
| var instances = []; | |
| foreach(dependencyOf(Constructor), function (Dependency) { | |
| var dependency; | |
| if (Dependency.length) { | |
| dependency = ioc(Dependency, previous); | |
| } | |
| else { | |
| dependency = singletons[Dependency.toString()] || new Dependency(); | |
| } | |
| instances.push(dependency); | |
| }); | |
| return create(Constructor, instances); | |
| } | |
| ioc.singleton = function (Constructor) { | |
| if (typeof Constructor === 'object') { | |
| singletons[Constructor.constructor.toString()] = Constructor; | |
| return; | |
| } | |
| singletons[Constructor.toString()] = new Constructor(); | |
| }; | |
| function dependencyOf (Constructor) { | |
| return map(parametersOf(Constructor.toString()), function (parameter) { | |
| var DependencyName = capitalize(parameter); | |
| try { | |
| var Dependency = eval(DependencyName); | |
| return Dependency; | |
| } | |
| catch (e) { | |
| throw new Error('No type ' + DependencyName + ' in scope, ' + | |
| 'which is a dependency of ' + Constructor + | |
| '\n' + e); | |
| } | |
| }); | |
| } | |
| var PARAMETERS_REGEX = /\((.*?)\)/; | |
| function parametersOf (constructorString) { | |
| var matches = constructorString.match(PARAMETERS_REGEX); | |
| return matches[1] && matches[1].replace(/ /g, '').split(',') || []; | |
| } | |
| function capitalize (string) { | |
| return string[0].toUpperCase() + string.slice(1); | |
| } | |
| function create (Klass, args) { | |
| function F () {} | |
| F.prototype = Klass; | |
| var instance = new F(); | |
| Klass.apply(instance, args); | |
| return instance; | |
| } | |
| function map (array, fn) { | |
| var result = []; | |
| foreach(array, function (el) { result.push(fn(el)); }); | |
| return result; | |
| } | |
| function foreach (array, fn) { | |
| for (var i = 0; i < array.length; i++) fn(array[i]); | |
| } | |
| })(); | |
| /* example */ | |
| function Service () { | |
| this.name = 'the service'; | |
| } | |
| var i = 0; | |
| function Messages () { | |
| this.welcome = 'hello from messages #' + i++; | |
| } | |
| /* singleton Messages */ | |
| //ioc.singleton(Messages); | |
| /* or, use a specific instance for all Messages */ | |
| //var messages = new Messages(); | |
| //messages.welcome = 'hello there!'; | |
| //ioc.singleton(messages); | |
| function Controller (messages, service) { | |
| this.service = service; | |
| this.messages = messages; | |
| } | |
| function AnotherController (messages, service) { | |
| this.service = service; | |
| this.messages = messages; | |
| } | |
| console.log(ioc(Controller)); | |
| console.log(ioc(AnotherController)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment