Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple instances on one page with Javascript

Tags:

javascript

I'm having trouble figuring out how to handle multiple instances of some javascript functions that I want to run on a page. It's part of a custom analytics project that I'm working on.

I have a function called initData(); The function uses a setInterval to call another function that sends a ping to my server every 1000ms.

The problem is that I want to be able to have more than one instance of this function on a single page. My current problem is that as soon as the second instance is called it overwrites all the variables from the first.

What's the best way to get around this? Is there a way to make the functions seperate and/or private instances so that they don't interfere with each other?

like image 466
sicr Avatar asked Jun 21 '11 09:06

sicr


1 Answers

By default all variables (and therefore also function declarations) live in the global namespace.

The only way to introduce a separate namespace in javascript is with a function call. This is how you do that:

 (function () {
     /* your stuff here */
 }());

You wrap your stuff in an anonymous function, and then call it immediately. This way your functions will be separate, even with the same name.

Example

So, for instance, if you have code like this:

var my, local, data;

function initData() {
    // use my, local and data here.
}

and you have someplace else:

var some, other, data;

function initData() {
    // use some, other, data here.
}

then one initData will overwrite the other initData. However, if you wrap each in its own (function () {}()); then they will be separate.

(function () {
    var my, local, data;

    function initData() {
        // use my, local and data here.
    }
}());


(function () {
    var some, other, data;

    function initData() {
        // use some, other, data here.
    }
}());

Be aware though, that these names are no longer in the global namespace, so they are also not available for use outside of the anonymous function.

One global

To control how much and what you expose in the global namespace, it is custom to expose what you need through one global object, usually in all capital letters.

FOO.module1.initData();
FOO.module2.initData();

You would do this by making sure FOO exists, and if it doesn't: create it.

var FOO = this.FOO || {};

The same for your module namespaces:

FOO.module1 = FOO.module1 || {};

and then inside of the anonymous function, expose what you want.

Complete example

module1.js:

var FOO = this.FOO || {};
FOO.module1 = FOO.module1 || {};

(function () {
    var my, local, data;

    function initData() {
        // use my, local and data here.
    }

    FOO.module1.initData = initData;
}());

module2.js:

var FOO = this.FOO || {};
FOO.module2 = FOO.module2 || {};

(function () {
    var some, other, data;

    function initData() {
        // use some, other and data here.
    }

    FOO.module2.initData = initData;
}());

controller.js:

FOO.module1.initData();
FOO.module2.initData();

A last tip

The controller like written is dependent on both module1.js and module2.js and needs to be loaded last. That can be avoided using something like jQuery's document.ready, making it wait for all scripts to load.

jQuery(document).ready(function () {
    FOO.module1.initData();
    FOO.module2.initData();
});

If you're not already using jQuery, you can use a small script like domReady to avoid the bloat.

like image 163
Magnar Avatar answered Nov 10 '22 18:11

Magnar