Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Measuring pollution of global namespace

Background

I'm trying to refactor some long, ugly Javascript (shamefully, it's my own). I started the project when I started learning Javascript; it was a great learning experience, but there is some total garbage in my code and I employ some rather bad practices, chief among them being heavy pollution of the global namespace / object (in my case, the window object). In my effort to mitigate said pollution, I think it would be helpful to measure it.

Approach

My gut instinct was to simply count the number of objects attached to the window object prior to loading any code, again after loading third-party libraries and lastly after my code has been executed. Then, as I refactor, I would try to reduce the increase that corresponds to loading my code). To do this, I'm using:

console.log(Object.keys(window).length)

at various places in my code. This seems to work alright and I see the number grow, in particular after my own code is loaded. But...

Problem

Just from looking at the contents of the window object in the Chrome Developer console, I can see that its not counting everything attached to the object. I suspect it's not including some more fundamental properties or object types, whether they belong to the browser, a library or my own code. Either way though, can anyone think of a better and more accurate way to measure global namespace pollution that would help in refactoring?

Thanks in advance!

like image 276
mbeasley Avatar asked Aug 20 '12 14:08

mbeasley


People also ask

What is global namespace pollution?

Polluting Global namespace causes name collision. This name collision is very common in large projects where we may be using several javascript libraries.

How does namespace help in preventing pollution of global namespace?

Technically, namespace pollution is simply leaving your symbols in a namespace where they shouldn't really be. This doesn't necessarily lead to clashes but it makes it more likely. both of those functions are made available to the linker.


1 Answers

So after some of the comments left by Felix Kling and Lèse majesté, I have found a solution that works well. Prior to loading any libraries or my own code, I create the dashboard global object (my only intentional one) and store a list of objects attached to window via:

var dashboard = {
    cache: {
        load: Object.getOwnPropertyNames(window)
    }
};

Then, after I load all of the libraries but prior to loading any of my own code, I modify the dashboard object, adding the pollution method (within a new debug namespace):

dashboard.debug = {
    pollution: (function() {
        var pollution,                                     
            base = cache.load, // window at load         
            filter = function(a,b) { // difference of two arrays
                return a.filter(function(i) {
                    return !(b.indexOf(i) > -1);
                });
            },                          
            library = filter(Object.getOwnPropertyNames(window), base), 
            custom = function() { 
                return filter(Object.getOwnPropertyNames(window),
                        base.concat(library)); 
            };       

        delete cache.load;

        pollution = function() {
            console.log('Global namespace polluted with:\n ' + 
                    custom().length + ' custom objects \n ' +
                    library.length + ' library objects');

            return {custom: custom().sort(), library: library.sort()};
        };

        return pollution;
    }())  
};

At any point, I can call this method from the console and see

Global namespace polluted with:
53 custom objects
44 library objects

as well as two arrays listing the keys associated with those objects. The base and library snapshots are static, while the current custom measurement (via custom) is dynamic such that if I were to load any custom javascript via AJAX, then I could remeasure and see any new custom "pollution".

like image 145
mbeasley Avatar answered Oct 16 '22 04:10

mbeasley