4

I'm dealing with a huge javascript codebase that I'm trying to reorganize. I'm not really an expert and I just started studying good javascript coding practices. So, one thing I'm trying to do is to divide all the code in modules. In this particular case I'm trying to create a module that would help me to optimize video embeds. I would like to pass the module an id and receive some html code or an image out of it.

I'm not putting the whole code here, but it's enough for the example:

var videoIframe = (function($) {
    'use strict';
     var id,

    setVideoId = function(videoId) {
        id = videoId;
        console.log(id);
    },
    getVideoThumbnail = function(videoId) {
        setVideoId(videoId);

    },
    test = function() {
        console.log(id)
    },
    getVideoEmbedCode = function() {

    };

    return {
       test: test,
       getVideoThumbnail: getVideoThumbnail
    };
})(jQuery);

In another module I assign it to two variables:

    var video1 = videoIframe;
    var video2 = videoIframe;

    video1.getVideoThumbnail(123);
    video2.getVideoThumbnail(456);

    video1.test();
    video2.test();

And, of course, I'm not getting what I expected. After the second getVideoThumbnail call, it always prints 456.

Doing some research I understood that I'm creating a singleton, a single instance, and I'm only changing values inside that instance. I think I need a constructor for my module, but I'm not sure how to create it in combination with the IIFE pattern. And is it the right approach?

4 Answers 4

6

And is it the right approach?

No. IIFEs are for things you want to do exactly once.

If you want to do something multiple times, then use a regular function and call it multiple times.

var videoIframe = (function($) {

    function videoIframe() {
        'use strict';
        var id,

            setVideoId = function(videoId) {
                id = videoId;
                console.log(id);
            },
            getVideoThumbnail = function(videoId) {
                setVideoId(videoId);

            },
            test = function() {
                console.log(id)
            },
            getVideoEmbedCode = function() {

            };

        return {
            test: test,
            getVideoThumbnail: getVideoThumbnail
        };
    }

    return videoIframe;
})(jQuery);

var video1 = videoIframe();
var video2 = videoIframe();

video1.getVideoThumbnail(123);
video2.getVideoThumbnail(456);

video1.test();
video2.test();
Sign up to request clarification or add additional context in comments.

2 Comments

so why are you still keeping the IIFE in your example?
@Carlo — Because there is still something that needs to be done once (which is make the $ variable available). The code that needs to be called repeatedly is moved into a function of its own and returned from the IIFE.
1

The problem is that you are initializing object when assigning to videoIframe variable:

var videoIframe = (function($) {
  // ...
})(jQuery);

You can try with:

var videoIframe = (function($) {
  // ...
});

var video1 = videoIframe(jQuery);
var video2 = videoIframe(jQuery);

Comments

1

Just keep videoIframe as a function that returns your IIFE, instead of reusing the singleton. I kept the IIFE so the id and the inner functions keep being encapsulated and hence, not reachable if they're not in the returned interface object. If you are planning to create alot of these, it might be more efficient to just use a constructor and a prototype, so the inner functions don't get recreated for every instance.

var videoIframe = function() {
    'use strict';
    return (function() {
        var id,
            setVideoId = function(videoId) {
                id = videoId;
                console.log(id);
            },
            getVideoThumbnail = function(videoId) {
                setVideoId(videoId);

            },
            test = function() {
                console.log(id)
            },
            getVideoEmbedCode = function() {

            };          
        return {
           test: test,
           getVideoThumbnail: getVideoThumbnail
        };
    }());
};

Comments

1

I did some minor modification. Hope it will be helpful

    var videoIframe = (function($) {
    'use strict';
     var id;

    function _setVideoId(videoId) {
        id = videoId;
        alert(id);
    };
    function _getVideoThumbnail(videoId) {
        _setVideoId(videoId);

    };
    function _test(){
        console.log(id)
    }
    function _getVideoEmbedCode() {

    };

    return {
       test: _test,
       getVideoThumbnail: _getVideoThumbnail
    };
})(jQuery);

Now you can call like this

 videoIframe.getVideoThumbnail(123);
 videoIframe.getVideoThumbnail(561);

jsfiddle

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.