Dependency injection in Javascript using InfuseJS
Published: 2024-04-10 08:23:44

Dependency Injection (DI) allows to obtain instances of classes without having to create them explicitly.

DI reduce the coupling in your application and facilitate the testing.


InfuseJS (by the creator of SomaJS) allows DI in vanilla JS

Here is a [Demo](https://flems.io/#0=N4IgtglgJlA2CmIBcBWAjAOgBxYDQgDMIEBnZAbVADsBDMRJEDACwBcxYR8BjAeytbwByEAB4S8bqwj8ABN1g0SJALwAdEM3g0o8AE4aAfGqqyzo5gGZDAEXgAHIbqrcAnrIhUAVpOlzPsgBSNABuNADK3HoQ9qyiAPRWxqbmNLLMevAE6iBGJmYFomkZWSoA5Gys9iRI8fEA5hCszACuAEYYfGDxJLwtVFAkgvbxngQtEmWGAO5NzLIAklTjEoEkCTTJhfGb+eb2WwWybe7N8PKZNKy8erK8BLJF6ZnZFaxVtT28YDReJBiNZrtDAyL4-P7xADE8Sm4W+NEC4Q2hwSBxMCQkUhkVGS4l82PkimUOSgEBI9kUrjyKUepJCHigOVo9CMCTph1pEHp0ByNHq8FZ8XZ6J6+P4uMxflMCiUqg0P081MKkoJMuJGgINzASqOnJCHN1etkQ1cCBy9h0pKo9SQAAYMChMtqQAbDeZFG14LBDAA5OjwBIer2ut2iTz2FqsBlM-0AWnDkY0sniIe2wpphtE6bdutEQe9AEF+YGaJ7vXsc+YE1GeRo+fB41QI6wk8nU+YhVyQ2yuxWMWKcX26cbWKb4DlBAAPVixmiwCD1KhIbhCQQGF0VwptSPXUz8BQQbgAaxyfAEel4sAQegwLXsUCu8BsVxoAAoAJRGACq98fsgAahA8DTAk27vOKfadvqIoqhBVBcCAEgIFi-BkIwABsSDoSgIAAL64NQ-oiGMEzwBgfwIWegjCIw8QAFQeMspGyLGsghJYGD2mgLGyGgtrxGgABM8SCbaaAAJw8ZU1SfICrQdF0Xz9IMwyjExEiyHR8QmAAhOMLhSq+rDvsAGjMUM0RSBoADcYS3HoKjxAAevpKFUGoagkHR5BOR5r4ALp0X5Hlea+Pkee+gWfmo77xGAuBUI5r4APx6f0bnRV5Z4WS0Ug3CF3m+Wor4AD6uVKgXBZ5dFhUVkV0dFmV0cAcW4OO8S4B1ECOUVoUAPrJe+r4eeEADUg0eWgBUACQdbwSXDWo2lLRgdHTe+JWLct3khSNgXJR5QVLe+sX1GA1msBg+gXnoqjAAAsgWAAKT0LD6ADifUAEIFjYfVPQASgA8k9SAaOQACieg3Ys3i+DcGCPS9b2fT9f2AyD-myAAKloshELdUYWno-prh4JCMWE85QLgshpBZnj1OTsjwJOjhSPAUAYBouBI69H3fb9fX-gWAAyX4Q2DICQ9DNywz4eU3nzKOC39IvixDWO4+cmL8FAsjE6T+jM54VPQLTTTyDQVBlFGVAtFedy3MpWSeJztOzM0BsXo4eijkgsg88rAto31ADCosFuE4RSzLMNLAr1xK89-Oo0LEdR+EWt47rAwGzQJP0GTZKU3O5t0-j6VSszrPs4INOyJ78z2D7+j+4HXDB2nf3hCjosQ9jQM+rHUPx3DiuIynKuh73H394PPrZ+czQQHo+uG0Xxsl6bZcN2kbS8Je2imCXte+O7jdzN7vC++3QdTwLYsAxDv0AJp9RDAAaCzhNjMfg6POWCd4bJ2Ro-UWz834f2-r-LOONmAlx+PYewjM6awEuFAdwrMySsBIB7K+Lcb5t1cAHHmYdIHYwhn1N6v8Cw+jDlQt66sFjowLADAs90R6y1uMAie5CX6UOoT6Wh9DGE+mYaw9h90sZLDNuvAuRs9C0zSOVAkp82bny5jzH0QM+pdz6gAMSBl+H0NguFj0TgjHReiH6fSMSYmwWMfS8FkEglB1p8Z9AGDzN6gQIZh2xkIkRDChHUL-hDUWBj-rAyehDAG2NX7mKAePJOGBfH+MCTQ7GdCQlvTCeECJUSMaxPia-LGBZXFXG4AgjxhDb7uGYEoY48AhCeOUoxWQZxOkF35KwWmrg+hWxtjWFJdMT5UCGNbFcHSmhIQINzLg6SAlBOyaI0JCxwmRPDkPX+AMvwBKBgDJJPCUkIyWZk4Rqzck+nyYU7Zly9kHIBuUyprBqmoOyqwPQuUk750LvAMmjSKaelaZqdpAQumsB6QC-pgzuDW1toxROYzGKTJcOcAIsyvTzJ5jYCGsTTEQ3oQsCG4Q9E-1np9PJuyFjLPukDPFSAyhx2SZYm8eKCV4uJaS8l0cVbUuxgDWlgT6V4vKaYDQnhE5JjqcQ2Qr4C4k1cO+TpjSoy6BIFECAnoKZdN0I4AYQhuBAQpogskJBUEBAZlIVxvBdAYDKLgDlRKuVhxJWS+6FL+U3JpXShlVCw47MFfsweAMhF+ICQsIeTKWUnLZRgZ1hLuUeq9QLAVQq-V4vubskNhzw0ZKjYvWQBYJUgClb4GVrc-buAVdDGgyrVVXFkBqrVOrVXnH1U4I1Jq7gPE+d8xWzNIDKEtaYa1UYwB2rIo6xNrr3VCIkX1bJAN3oD2OfLEBCb8UuqJW6nlTCxYsKXWw1d2MZFUDkd0vQvTlGVwMgSOWaQ1SmopmfDm+ta0XmmHetyQyqC8CjJ6VFUKBAQEfFAd8CzcK2QLsaFQqj+BGVwEoqgbUTIr3+HUlQfSMMYCpi0ccSjcMKBUKh3DFrrQIF3CoeAJUSo6TQPhGg8Gq7YlfHoEyEACDDUQl8xmGgdLYdcI4e4sgOPNC-bIKgwFZCAL0EZK63D-j6NDsU98+F7AsfvYhlDnHuMIaoEhjjwBNTybslJ7DGAEDWmaNZKgsZYzWXfFxoy5AqD+RUJ5jjmRWAtD0FQHStprI+b8wFxjCnel2ANc4Y18ASCvioO+ZDJ0JO8G-dJ79cmFPXRuP8c5KycliNuVswNDzc0A3U7gbgWm3LsYSiZcz44Qi8GgLIW0gmVB6GSmUTxtwunlt-cyeApCQBlFGnoUaZQNBlCljzbqzXWvtc81QbrjctDjLRdIK4jMRtjaoJN6bs2QDBYBaFzpimbr-Gsfo+xpjRrwFGhAUaGgoMXTSachyBmPzAFw24xmd18K4eJquUjDtYC4HI3xqQ90p0qAYxDhB-xx0w90GHVCXyfk3F4VKOHaAEdkgwKl6YQMqD3XNYzOHtpAcAgBVFrtLgTU1cMiQBrsGaC4E0+Qfy1kDPyCM-V4A9gMARhIMwBL6n-hAqBtMKgT0q2jh4wNlsIB3wADJVfg14G0ZFBY62uH8hoTzKggba98MLi81xRyOEJ7wcIfHrSdDnLAV8-wldq9V67lJVmhD1GaIYW06uFUqE94nd8MHbjMFwC0YPNu7fRGtB+DAmQKQ0BXK+XguANAaDDy520RuWggkNZOIG3GNDPuz++ZgKgC-J8UGn+IvP+2Y70A0TPuQVcYB+G8sXiXrJegkMAXPHWC+eF0MX0vhBWP8Ar0TqTMmsuXRy7dLdnLd3zoPaLI9y7T1h6rwXrv1T2PqZc8wd8pnXzmYWCoZg5A0D+QwOSecrBXzwCSxDFQtpcCwBUAsb3NnmDWQQx5iAGjSjSs63DZALCQz36P5NA8Y5DvjkC2j3616p7wCvjLQkCt5Z4q7WQKrq40DQHJSEGaxIAECQaoFp4QBVbqYhb+YGzU7Y4IyEKW7CbjjABRDaCCBhwIKwBQBkFT6GbgFiakYyaXRMF6Ana+b0E3jA4CDYaI7IYP5Q6sAo7jiQ6WSqFTpKHI5Tpo4TIY6KzY7YgKEE66Go7o4DpJzGH8BKFE4k5k4jrWimH-D2Gk7k7WjIb4S9L3Q0DIKMz-i8ACHaaGbGTAB0GmC-Z+HuL1AkDJRRH+HWgkDkCsD+TxGI6d7RH-YpH+RIBA4FyrjpEE5yGXQ+FZHWiBFGTvhID2xXg1Fg74RIL-hzgEbBG1a6aD7cYJExHJF6D+Tviz4ZaybcLZZKaTxgKfRPwvw2Dvxfw-x-zjZh4RF0xH64BfYdEua1Hf6kYDEZBpZz6ZYjGL5jEqZCzqwSyLG4R1aJb47-B-ZJHkB9GiHfrxYoa4ALb6yf4fFtZJYYaNF+FhxEg1DrEJRoadFGQZH3GxGPH9GDHz5HEXa5bjGpx9RTFQJzGwKLFSFnZvgcZrGCHXF6Y8YGYCZCYiYPCJZwmHE3SjGXbInTzpyRzRyXGEltTq4gmJbgkaAHxHzWyklW7wCiaUl7Hpbwk0nHF0mnE9x9wDxDwslKKv63GZGJHQlPFDGvEJRg6gmKl-HIbwCTohDwC+EqltGGRhHLHdHZGpGg5Xi4C6BUbLyQnlHQmpG3H4RArGkxGmlsbmmnb+Y6Q6SWkPGpHulKBLBaDRD1yek7Zfa+nSEBaBkZFlEqmVHGTeEArRnWjemIZhHn7ma3AQpOkqks4uZBmxEsBKDS6y7y6uBH7CGJRlm9Hc6bF4YtHjieasB0ZUCdDbHYbvjLHdl1K4TpmsDNGwCtGxnCEOSNk5HWQuY6TGbzn5GZACBEm4ZuGOEUb1C7GSZDFZbcBVFLF+lUC4TTkZElE06qHOmBEYDRGwC1nLmri4A9ItD0ACAs64QuY3gKD1kqC65Krm4AYAZsEP7zgriO5Xi1r1Cvmrgs7Yn0FUBIEebfng43hblUb8DJTsatnjm0abQ3j4bqEZGcGPhLBorgV3kPmKGJZJYEVtnVHEaXCCBkUgYUXIL3kQlkj1annHliY4UEYjmAmyjZmhFTkuHKk9GznzmLncaJnFEFGrkRHBbiUXnJkxE3mUWcWYYKV9Ivlvm4LH7cYoX9m8UoX4SeCbZgaCAiVH5cmT4hH8lsGibiYikHHDHimInL78IFiCJZKFYLqHqSIcJh7mYNmXl06GoM5xZH5zldEZHmHwDq4LkVkkBVly5ELVqK4pIz6uV7kIlL7-Czpr48qep8ppo+qCrCp6L+o55xVmEqFqH6E5RGEpLYjq7dnWa+7MD+5JU3hS4y7pX1JZXSoq47n7F5UeUFUr47rJq8qUqhK+oir+rZrBpPL5qRpDxh55mwbjhuZg7+S4DdSf7zQdU+62YQCiC8BzmgHObcZ6WwV-5dWGBPZoDq7fFLYqD3XvnkAvX+TtVg4dZfW4I-WjR37vhkQi5i5A3JG-Vh797wDADmaqCIUQAHXMa4ZqUBG8Au61UKrCGaYY0ArY6cxjkEYKq4BwUQ0TBi72Dqbw3gnrkikOEeHblUnuU3CvgHl4I3hDYnR97C7U0X4tafHqY8XxkHGvgGKCGAWsHW5tCj63nsW1kKknTmUpI2V9LGbbW3DjKqryUrmsDq6PkCCF6JxIaBa-FFk9G3VaUSX-YpVpU1ni7CFEUE6Y0VHY294Kb9XVkZUK4Q0+wbQlSXRN6KxG2dCWHN4y3AWODh2h2pIsEx1kQ+2DXEIv6AW03u6ububiW9LE1QCk3oHwD1a0HHkaiCGOXknnb2C8BDBNWGGdklR6B0aXQ1112R1SAfhum4B50pIk1tk2UdGNaHWdb8XwDwWmAoWB5oWMwYUrbYWEV0avj2AJZKE-lKGEXiUWUgZbaCDYXr2EZj1JbdR0W4XVHL2r3GVtQqDdS4bb3Wy73oHGUnRsmq6vhpQhGEngndkp1O0cZjWinUkc0SlIn5Z+VrJ5IbIFJbLFJxIJLqar06kZFK4v4v0QD4QkXMUGFTLDZfbCGsBb3YOgaPiK0UhUVcXQ1Hni130pJVEQ4jmF0GIXhgBCXKAa0mTa1iYdKNk22NkO0DV-0nSI2wYNlW3ZF9GxUJY9lG7GQDkP6z0AqYVSOL2bTdmb2MVcHwAsU4OkMcUYbPnXowXvkv1qP0V5HEVMVaNENsVkNaUGPQX6Ufmlnnk6UmXUMuMG2XmMPMOsP-CaXG26WGOOO42M1frM1OGs25Vikc0HnvUQ4YC82Vakjki124MEnoZiNJEqDADDn4RS0hHR0CkYDy0DBL35NuSFMgUlOMiTnCP2QuGSPl0OUgCCYCnOUANuVZYaByawotCuITCAaj4VwGYLIhUiN-l66VPW4kBgVkTwqQXQ24BoBJbjh4MM2I7AY4Oiav51MeBM5sYmTQYQBTOH2J0Cnh53DPEeAU2j2aUZ7dlnjwrP7-n1onOgWHhzNO5QVGMGV83LEm5m0s5G5xE1C8Bi1nY3j+MJQR0uBXCvgvOuBvMzMfMQXO6UOq0T0sy4RJZNNuSG5kmCkPC6BEDSZvXC1tYdbEtuy3lgBQDq5UvSZ0NmSGokucyV2Eu2pQAOyJWq7vUdaTpcsIBXRsw3C4KB4CvcvCs11+yqDGRt4uystQDsvbMisyuB61yiuysIM0MrCu2e66t0Y5Nh4IRIQDhoQgBoBIAADsKAKAWAeEBEIAQ2Ig5EZAPA-A1ErAIgdQsgX40gT+7gvO1wsgvSKKXo+pq4xw7gLCJgnyLMsAUYKgDIsgKghgzavA3APzl5EMCA+lX0rgCwUAr40AYeJgJgPrahsAhIsosbQJsglbsgpkGY8dHNKqTbOYuGD4UKKbjbm4OYQ2I2gQvAzApgNgvAAoXAfbbo9YAclgtoU7Zg0Gm4uEZbGYEgrAz4UKCW-oyi-IbbC7et-wXbNACT-oPbQ21kB7nbL4t5-IPb9Yl7GYK77kGYkWL4H4vbGYRwFpGRx7j7Rwz7z75b8QAEQE365eLgdbgEMm7bBQyTKergm7b4x7+7X7BQXoz+GgQ22ehe0megAAEtjPdKLD2wAAYWDWD4deiwAuLTTADHunv0CyB0YdzJQHR4QJBJCkf-tugYc8b1g4eeB4eEfEdkcUeGCvyDIFGyB0cMf1jMclSsfse4SyCuDaC3R3B8GcfWDcfLsmBAdUA+v6FfKXjXjVvKC1uyiyDGcXhXjGywdmAtvyYCtei0whBgeocduQlTpVtJsuewBXsZHucyZJvBfTA8eLurtHB3hdtPjvueduhxtDY9t8dYdxjVg4eEURe6hxvydJupcgD1iNjNiZdtnZdHC-Y+cP607vtDa7uv7lcFC4ZhcYDweUhIe23+fhXxeltPv6ersVs0ABBBsuKeBNBgbzgABe5w1s+s3ykReMd5h4220+TEIRlSngH7DnyYIHYcljKKSu+UGY5mh3twSbQxJEEg72bKH4j7m4g39g5nEguqLi-WH2m4p3ypvjPG-nPM9bPnvXRwn3SC33GgYXf30H0wgPBQwPAJQJPGVEtn14f3Nnpn+gvXm45miPaPZ3SKm6vShdCPHrSP+g2ed3GYswAwaWMLJndnuP2PdPj7BnCoQh1kJr4bbk5r6Eto1rsYPPtoDrhE9ALr3AyglEHrq4IgB8mCn7ZgbQqeR49QF4ykSAbQdeR4PHfANHegy4rg1sTPq7LA2gugtwsHU4M4Zci4y4q4+gPHPw16ngsYB84EYASAgkToBvL7aQsHWvNwuv+v-XL7+YsvzaZICHSAng840mTvNHx4PHswUAzQqAto9gk4sgPH5vs484VvCABArA-7gfJgrXYflIIfmflvS4K4AgtvgcKQ8vx4SvXi-BavCvmvl4fvugDg7iGvhf3ZpmYAIf9fivyvAwqv6vGfrMFv2flfNvkhewB8a8+gSAaAqfxol4rWbgAfKQ9vjQS4todMkYV1ewCfSfAALLaCn5ODxxaDADtmgB7732BLuIPwr43yr5v1QDxwvyb8v6v70NTPID16f89gbXetBHyoBR8GwavDNj32349JHe1wewMvwf4nl2eyEKUOa0EiCQ3eaAPCAdSdZERGA90f8GHDtyPgS8uuVgEsF1aIhYwgkPCEAA) 

```js
// Helper
const elt = id => document.getElementById(id);


class Model {
    constructor() {
        this.data = {
            name: "John Doe",
            age: 30
        };
    }

    setData(name, age) {
        this.data.name = name;
        this.data.age = age;
    }

    getData() {
        return this.data;
    }
}


class View {
    displayData(data) {
        elt("name").innerHTML = `<h3>Hello ${data.name || "??"}</h3>`;
        elt("age").innerHTML = `<h3>You are ${data.age || "??"} years old</h3>`;
    }
}

class Controller {
    constructor(model, view) {
        this.model = model
        this.view = view;
    }

    updateData() {
        const name = elt("name-input").value;
        const age = elt("age-input").value;
        this.model.setData(name, age);
        this.view.displayData(this.model.getData());
    }
}


function main() {
   
    var injector = new infuse.Injector();

    injector.mapClass("model", Model);
    injector.mapClass("view", View);
    injector.mapClass("controller", Controller);

    var controller = injector.getValue("controller");

    window.controller = controller;
}

main();
```