Javascript 测量全球环境污染 背景
我正试图重构一些又长又难看的Javascript(可耻的是,这是我自己的)。我开始学习Javascript时就开始了这个项目;这是一次很好的学习经历,但我的代码中有一些垃圾,我采用了一些相当糟糕的做法,其中主要是全局名称空间/对象(在我的例子中是Javascript 测量全球环境污染 背景,javascript,namespaces,refactoring,Javascript,Namespaces,Refactoring,我正试图重构一些又长又难看的Javascript(可耻的是,这是我自己的)。我开始学习Javascript时就开始了这个项目;这是一次很好的学习经历,但我的代码中有一些垃圾,我采用了一些相当糟糕的做法,其中主要是全局名称空间/对象(在我的例子中是窗口对象)的严重污染。在我努力减轻上述污染的过程中,我认为测量它会有所帮助 方法 我的直觉是,在加载任何代码之前,在加载第三方库之后,最后在执行代码之后,简单地计算附加到窗口的对象的数量。然后,当我重构时,我会尽量减少与加载代码相对应的增加)。为此,我使
窗口
对象)的严重污染。在我努力减轻上述污染的过程中,我认为测量它会有所帮助
方法
我的直觉是,在加载任何代码之前,在加载第三方库之后,最后在执行代码之后,简单地计算附加到窗口的对象的数量。然后,当我重构时,我会尽量减少与加载代码相对应的增加)。为此,我使用:
console.log(Object.keys(window.length)
在我的代码中的不同位置。这似乎工作正常,我看到数字在增长,特别是在我自己的代码加载之后。但是
问题
只要看看Chrome开发者控制台中窗口对象的内容,我就可以看出它并没有计算所有附加到该对象的内容。我怀疑它没有包括一些更基本的属性或对象类型,不管它们是属于浏览器、库还是我自己的代码。无论如何,有人能想出一种更好更准确的方法来度量全局名称空间污染,从而有助于重构吗
提前谢谢 根据经验,您选择的常规模式工作正常。然而,有两件事你可能需要考虑(作为补充或替代):
使用或与现有代码一起使用,并查看产生的错误。它应该可以帮助您快速、轻松地发现大多数(如果不是全部的话)全局变量的用法(例如,您将看到“未定义”变量的错误)。这是一个非常简单的方法。因此,本例中的度量将仅着眼于问题的总数
我们发现Chrome可以让检测窗口对象上泄漏的资源变得棘手(因为在运行页面的过程中添加了一些东西)。例如,我们需要使用RegExs检查返回的某些属性是否为本机属性:/\s*函数\w*\(\){\s*\[native code\]\s*}\s*/
来发现本机代码。在我们编写的一些代码“泄漏检测”中,我们还尝试(在try-catch中)获取属性的值,以验证它是否设置为值(而不仅仅是未定义的)。但是,在你的情况下,这不应该是必要的李>
所以在和留下一些评论之后,我找到了一个很好的解决方案。在加载任何库或我自己的代码之前,我创建仪表板
全局对象(我唯一的目标对象),并通过以下方式存储附加到窗口
的对象列表:
var dashboard = {
cache: {
load: Object.getOwnPropertyNames(window)
}
};
然后,在加载所有库之后但在加载我自己的任何代码之前,我修改了仪表板
对象,添加污染
方法(在新的调试
命名空间中):
在任何时候,我都可以从控制台调用此方法并查看
全局命名空间被以下内容污染:
53自定义对象
44库对象
以及两个列出与这些对象关联的键的数组。base
和library
快照是静态的,而当前的自定义度量(通过custom
)是动态的,因此如果我要通过AJAX加载任何自定义javascript,那么我可以重新度量并看到任何新的自定义“污染” 例如,有什么附加到窗口
,但在您检查它时没有显示?@Utkanos,例如-在Chrome中,如果我导航到关于:空白
,只查看对象。键(窗口)
,只返回8个键([“顶部”、“窗口”、“位置”、“外部”、“Chrome”、“v8Intl”、“v8Locale”,“document”]
)。但如果只检查控制台中的窗口
,就有几百个键……我同意Felix的观点,但如果出于其他原因需要获取不可枚举的属性,则可以使用getOwnPropertyNames()
然后沿着原型链走。Firebug呢?它显示了所有全局函数和变量。我同意这些添加。我使用JsLint,我发现它非常有用(但从未用于此目的。我想我会开始使用它)。@WPCoder您能澄清一下如何在从循环返回的所有对象上实现#2吗(在值上使用toString),该正则表达式用于查看它是什么类型的对象——如果它是内置的本机代码,则会被忽略。我们发现这些是在拍摄初始快照后的不同时间添加的(与您所做的非常相似)。我明白了。这非常有用。我必须实现它!谢谢。
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;
}())
};