Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Approaches to modular client-side Javascript without namespace pollution

I'm writing client-side code and would like to write multiple, modular JS files that can interact while preventing global namespace pollution.

index.html

<script src="util.js"></script>
<script src="index.js"></script>

util.js

(function() {
    var helper() {
        // Performs some useful utility operation
    }
});

index.js

(function () {
    console.log("Loaded index.js script");
    helper();
    console.log("Done with execution.");
})

This code nicely keeps utility functions in a separate file and does not pollute the global namespace. However, the helper utility function will not be executed because 'helper' exists inside a separate anonymous function namespace.

One alternative approach involves placing all JS code inside one file or using a single variable in the global namespace like so:

var util_ns = {
    helper: function() {
        // Performs some useful utility operation.        
    },
    etc.
}

Both these approaches have cons in terms of modularity and clean namespacing.

I'm used to working (server-side) in Node.js land where I can 'require' one Javascript file inside another, effectively injecting the util.js bindings into the index.js namespace.

I'd like to do something similar here (but client-side) that would allow code to be written in separate modular files while not creating any variables in the global namespace while allowing access to other modules (i.e. like a utility module).

Is this doable in a simple way (without libraries, etc)?

If not, in the realm of making client-side JS behave more like Node and npm, I'm aware of the existence of requireJS, browserify, AMD, and commonJS standardization attempts. However, I'm not sure of the pros and cons and actual usage of each.

like image 397
dgh Avatar asked Nov 22 '12 22:11

dgh


People also ask

What is namespace pollution?

Namespace pollution is a lot like pollution in general. It means that something is misplaced. In programming that means that code that should really live in separate namespaces is added to a common namespace (in some cases the global namespace).

What environment does client side JavaScript need to run in for it to be used?

Client-side means that the JavaScript code is run on the client machine, which is the browser. Server-side JavaScript means that the code is run on the server which is serving web pages. Save this answer.

What is modular approach in NodeJS?

In Node. js, modular systems are implemented natively, based on the common JavaScript specifications. This way, you implement a local namespace within every module. It contains variables, and properties that are private to a module until explicitly exposed/exported to other modules.

What is modularization in JavaScript?

Modularizing ensures that external functionality is created in such a way that it isn't dependent on other external functionality, a concept known as loose coupling. This means I can use a Foo module, without having to include a Bar module, because Foo is tightly dependent on having Bar included.


2 Answers

I would strongly recommend you to go ahead with RequireJS.


The modules support approach (without requires/dependencies):

// moduleA.js

var MyApplication = (function(app) {

    app.util = app.util || {};

    app.util.hypotenuse = function(a, b) {
        return Math.sqrt(a * a + b * b);
    };

    return app;
})(MyApplication || {});

// ----------

// moduleB.js

var MyApplication = (function(app) {

    app.util = app.util || {};

    app.util.area = function(a, b) {
        return a * b / 2;
    };

    return app;
})(MyApplication || {});

// ----------

// index.js - here you have to include both moduleA and moduleB manually
// or write some loader

var a = 3,
    b = 4;
console.log('Hypotenuse: ', MyApplication.util.hypotenuse(a, b));
console.log('Area: ', MyApplication.util.area(a, b));

Here you're creating only one global variable (namespace) MyApplication, all other stuff is "nested" into it.

Fiddle - http://jsfiddle.net/f0t0n/hmbb7/


**One more approach that I used earlier in my projects - https://gist.github.com/4133310 But anyway I threw out all that stuff when started to use RequireJS.*

like image 79
Eugene Naydenov Avatar answered Oct 27 '22 08:10

Eugene Naydenov


You should check out browserify, which will process a modular JavaScript project into a single file. You can use require in it as you do in node.

It even gives a bunch of the node.js libs like url, http and crypto.

ADDITION: In my opinion, the pro of browserify is that it is simply to use and requires no own code - you can even use your already written node.js code with it. There's no boilerplate code or code change necessary at all, and it's as CommonJS-compliant as node.js is. It outputs a single .js that allows you to use require in your website code, too.

There are two cons to this, IMHO: First is that two files that were compiled by browserify can override their require functions if they are included in the same website code, so you have to be careful there. Another is of course you have to run browserify every time to make change to the code. And of course, the module system code is always part of your compiled file.

like image 44
Lanbo Avatar answered Oct 27 '22 08:10

Lanbo