12

背景

我正在尝试重构一些又长又丑的 Javascript(可耻的是,这是我自己的)。我开始学习 Javascript 时就开始了这个项目;这是一次很棒的学习经历,但我的代码中有一些垃圾,我采用了一些相当糟糕的做法,其中主要是对全局命名空间/对象(在我的例子中是window对象)的严重污染。在我努力减轻上述污染的过程中,我认为测量它会有所帮助。

方法

我的直觉是window在加载任何代码之前,在加载第三方库之后以及最后在我的代码执行之后,简单地计算附加到对象的对象数量。然后,当我重构时,我会尝试减少与加载我的代码相对应的增加)。为此,我正在使用:

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

在我的代码中的各个地方。这似乎工作正常,我看到这个数字在增加,特别是在我自己的代码被加载之后。但...

问题

仅通过在windowChrome 开发者控制台中查看对象的内容,我可以看到它没有计算附加到对象的所有内容。我怀疑它不包括一些更基本的属性或对象类型,无论它们属于浏览器、库还是我自己的代码。不管怎样,谁能想到一种更好、更准确的方法来测量全局命名空间污染,这将有助于重构?

提前致谢!

4

2 回答 2

7

因此,在Felix KlingLèse majesté留下一些评论之后,我找到了一个行之有效的解决方案。在加载任何库或我自己的代码之前,我创建了dashboard全局对象(我唯一有意的)并存储了一个附加到的对象列表window

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

然后,在我加载了所有库之后,但在加载我自己的任何代码之前,我修改了dashboard对象,添加了pollution方法(在新的debug命名空间中):

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;
    }())  
};

在任何时候,我都可以从控制台调用此方法并查看

被污染的全局命名空间:
53 个自定义对象
44 个库对象

以及列出与这些对象关联的键的两个数组。base和快照是静态的library,而当前的自定义测量(通过custom)是动态的,因此如果我要通过 AJAX 加载任何自定义 javascript,那么我可以重新测量并查看任何新的自定义“污染”。

于 2012-08-20T19:57:20.277 回答
5

根据经验,您选择的一般模式可以正常工作。但是,您可能需要考虑两件事(作为补充或替代):

  1. JsLint.comJSHint.com与您现有的代码一起使用,并查看产生的错误。它应该可以帮助您快速轻松地发现大多数(如果不是全部)全局变量的使用(例如,您会看到“未定义”变量的错误)。这是一个非常简单的方法。因此,在这种情况下,测量将只查看问题的总数。
  2. 我们发现 Chrome 可以使检测窗口对象上的泄漏资源变得棘手(因为在运行页面的过程中添加了一些东西)。例如,我们需要检查返回的某些属性是否是原生的,方法是使用 RegEx:/\s*function \w*\(\) {\s*\[native code\]\s*}\s*/来发现原生代码。在我们编写的一些代码“泄漏检测”代码中,我们还尝试(在 try catch 中)获取属性的值以验证它是否设置为一个值(而不仅仅是未定义)。但是,在您的情况下,这不应该是必要的。
于 2012-08-20T18:18:23.727 回答