背景
我正在尝试重构一些又长又丑的Javascript(可耻的是,这是我自己的)。当我开始学习Javascript时,我就开始了这个项目;这是一次很好的学习经历,但我的代码中有一些垃圾,我采用了一些相当糟糕的做法,其中最主要的是全局名称空间/对象(在我的例子中是window
对象)的严重污染。在我努力减轻上述污染的过程中,我认为测量它会有所帮助
方法
我的直觉是,在加载任何代码之前,再次在加载第三方库之后,最后在执行我的代码之后,简单地计算连接到window
对象的对象数量。然后,当我重构时,我会尝试减少与加载代码相对应的增加)。为此,我使用:
console.log(Object.keys(window).length)
在我代码中的各个位置。这似乎很有效,而且我看到这个数字在增长,特别是在我自己的代码加载之后。但是
问题
仅从Chrome Developer控制台中window
对象的内容,我就可以看到它并没有计算附加到该对象的所有内容。我怀疑它没有包括一些更基本的属性或对象类型,无论它们属于浏览器、库还是我自己的代码。不管怎样,有人能想出一种更好、更准确的方法来测量全局命名空间污染,这将有助于重构吗?
提前感谢!
因此,在Felix Kling和Lè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,那么我可以重新测量并看到任何新的自定义"污染"。
根据经验,您选择的一般模式可以正常工作。然而,有两件事你可能需要考虑(作为补充或替代):
- 将JsLint.com或JSHint.com与现有代码一起使用,并查看产生的错误。它应该可以帮助您快速轻松地发现全局变量的大部分(如果不是全部的话)使用情况(例如,您会看到"未定义"变量的错误)。这是一个非常简单的方法。因此,在这种情况下,衡量标准将只是看问题的总数
- 我们发现Chrome会让检测窗口对象上的泄漏资源变得棘手(因为在运行页面的过程中会添加一些内容)。例如,我们需要通过使用RegExs:
/s*function w*() {s*[native code]s*}s*/
来发现本机代码来检查返回的某些属性是否为本机属性。在我们编写的一些代码"泄漏检测"代码中,我们还试图(在try-catch中)获取属性的值,以验证它是否设置为值(而不仅仅是未定义的)。但是,在你的情况下,这不应该是必要的