Search code examples
javascriptclassiife

Wrap static function (IIFE) into prototype


I wrote a function that I thought I'd only need to process 1 object but it turns out I need more than 1. I will use a simple example:

var Helper = (function () {
    return {
        el: null
        init: function(el) {
            this.el = el;
        }
        doStuff: function(){
            // Modify this.el in someway
        }
    };
}());

So then I'd just do Helper.init(el) on page load and then run Helper.doStuff() when I needed it.

Well now I have three elements who need this functionality.

My first idea was to just make it do Helper.init([el1,el2,el3]) and have it work on an array of elements but I may want to treat each element separately.

I am thinking the best approach is to probably turn the Helper IIFE into a "class" with prototype, but I am a bit crunch on time so I was looking for a way to make a wrapper to accomplish what I need.

I was thinking I can just take the function and not immediately execute it, and then somehow store that function into a prototyped function and utilize it that way.

Looking for ideas on how to best do this with minimal code change.


Solution

  • I am thinking the best approach is to probably turn the Helper IIFE into a "class" with prototype, but I am a bit crunch on time...

    I wouldn't expect it to take very long.

    I was thinking I can just take the function and not immediately execute it, and then somehow store that function into a prototyped function and utilize it that way.

    Looking for ideas on how to best do this with minimal code change.

    The class pattern is just one pattern in JavaScript, you can use that Helper just like it is as the prototype of other objects, which matches your "minimal changes" requirement. Just use Object.create:

    var helper1 = Object.create(Helper);
    helper1.init(el);
    var helper2 = Object.create(Helper);
    helper2.init(el2);
    var helper3 = Object.create(Helper);
    helper3.init(el3);
    
    // ...
    helper1.doStuff();
    helper2.doStuff();
    helper3.doStuff();
    

    If you add return this; to the end of init, that can be more concise:

    var helper1 = Object.create(Helper).init(el);
    var helper2 = Object.create(Helper).init(el2);
    var helper3 = Object.create(Helper).init(el3);
    
    // ...
    helper1.doStuff();
    helper2.doStuff();
    helper3.doStuff();
    

    Live Example:

    var Helper = (function () {
        return {
            el: null,
            init: function(el) {
                this.el = el;
                return this;
            },
            doStuff: function(){
                this.el.style.color = "green";
                this.el.style.fontWeight = "bold";
            }
        };
    }());
    var helper1 = Object.create(Helper).init(document.getElementById("el1"));
    var helper2 = Object.create(Helper).init(document.getElementById("el2"));
    var helper3 = Object.create(Helper).init(document.getElementById("el3"));
    
    // ...
    setTimeout(function() {
      helper1.doStuff();
    }, 400);
    setTimeout(function() {
      helper2.doStuff();
    }, 800);
    setTimeout(function() {
      helper3.doStuff();
    }, 1200);
    <div id="el1">el1</div>
    <div id="el2">el2</div>
    <div id="el3">el3</div>

    You could even keep using Helper directly on the first el, further reducing code changes, though I wouldn't recommend it.


    Alternately, wrap it in a function that returns it (and here I've also included that change to init):

    function getHelper() {
        var Helper = (function () {
            return {
                el: null,
                init: function(el) {
                    this.el = el;
                    return this; // <============== Added
                },
                doStuff: function(){
                    // Modify this.el in someway
                }
            };
        }());
        return Helper;
    }
    

    Then for your three places you need it:

    var helper1 = getHelper().init(el);
    var helper2 = getHelper().init(el2);
    var helper3 = getHelper().init(el2);
    
    // ...
    helper1.doStuff();
    helper2.doStuff();
    helper3.doStuff();
    

    Side note: You don't need the IIFE there anyway unless you have things in it that aren't shown beyond the object initializer...