rss feed

Javascript libraries conflicts

While browsing a corporate website, I could not help but notice that my browser kept complaining about errors happening on the page. I took a quick look and It turned out that most errors were due to conflicts between two libraries: mootools and jQuery. For instance, a property could not be found on an object. The failing code looked like $('#foo').setStyle(...). The debugger confirmed the fact that $('foo') was actually a jQuery object instead of a mootools object. So, what was going on ?

Javascript library conflicts

Most Javascript libraries declare a set of global objects or functions attached to window. Moreover, for the sake of convenience and conciseness of code, Javascript libraries often declare a single character variable name attached to the functionality they provide. For instance jQuery uses $, while underscorejs uses _. Conflicts may occur when two libraries using the same shortcut are linked in the same page, which is the case for mootools and jQuery. If both libraries are carelessly loaded within the same page, $ will be tied to the latest loaded library.

Q: How do we avoid such issues ?

A: Either we stop using the shortcut by directly using longer name variables attached to window (in jQuery's case, it is window.jQuery), or we use a mechanism that allows us to ensure which variable is tied to the shortcut.

First a few words on a particular Javascript pattern/construct

If you are a novice Javascript programmer, let me introduce you to a construct that you will encounter quite often:



(function() {
    console.log("very important log");
})();

For the untrained eye, what we have here is the definition of a function, enclosed within a pair of opening and closing parentheses, then followed by another pair of parentheses. It simply is a mean to define an anonymous function and execute it right away. Since the function definition is wrapped between parentheses, it is evaluated as an expression. Moreover, as it is followed by (), the function yielded by the evaluation of the expression is invoked.

You may even encounter another variation of the same pattern (for instance in bootstrap):


!function() {
    console.log("heya!");
}();

Why is it an interesting construct ? The answer lies beneath :)

Variables scope in Javascript

Unlike many mainstream languages (like C/C++ or Java), variables scope in Javascript is not restricted to blocks of code. Actually, a declared variable is reachable within the function where it has been declared, as well as the closures defined in the same function. The following piece of code illustrates my point.



if (true) {
    var str = "hi!";
}
console.log(str);

var foo = (function () {
    console.log("Hi from the anonymous function");
    var innerStr = "inner string";
    return function () {
        console.log ("I can reach the " + innerStr);
    }
})();

try {
    console.log(innerStr);
} catch(e) {
    console.log("oops, " + e);
}

foo();

Let's break it into smaller chunks.



if (true) {
    var str = "hi!";
}
console.log(str);

The intent is straightforward, I just want to show that despite the fact that str is declared within a conditional branch, it is reachable in the function containing the conditional.

The following piece of code is a little more convoluted.



var foo = (function () {
    console.log("Hi from the anonymous function");
    var innerStr = "inner string";
    return function () {
        console.log ("I can reach the " + innerStr);
    }
})();

I want to illustrate the fact that innerStr will be reachable within the anonymous function returned by the anonymous construct, however it will not be reachable outside.

Yet another convoluted example.



var foo = "foo",
    bar = "bar";

(function(foo, bar) {
    console.log("foo=" + foo + ", bar=" + bar);
})("not foo", "not bar");

Ok ... but what does it have to do with Javascript libraries conflicts ?

The anonymous construct can be used in order to control the scope of variables as well as the objects they refer to. For instance, in the case where jQuery and mootools are loaded, we can shield the code using jQuery as follows:



(function($) {

    //the code enclosed here can safely use $ as a shortcut
    //for jQuery

    $(function() {
        console.log("hi");
    });

})(jQuery);

However, a problem remains. If jQuery is loaded after mootools, $ will refer to window.jQuery. Thankfully, there is a mechanism in jQuery in order to prevent it from using $. All we have to do is invoke jQuery.noConflict().


jQuery.noConflict();
(function($) {

    //the code enclosed here can safely use $ as a shortcut
    //for jQuery

    $(function() {
        console.log("hi");
    });

})(jQuery);

Final words

In this article, I focused on the particular case of jQuery and mootools, but actually, this technique can be generalized to other libraries. Furthermore, it is a good practice not to pollute the global scope by using the anonymous function scoping, especially when writing a piece of reusable Javascript code.