如何在创建全局变量时记录有关全局变量的信息?

时间:2014-01-16 22:10:43

标签: javascript debugging global-variables google-chrome-devtools

背景

我刚刚了解到在DevTools控制台中调用keys(window)(或Object.keys(window))会显示全局范围内的变量(source)。我在StackOverflow页面上调用了该代码并得到了这个结果:

StackOverflow page global variables

变量i引起了我的注意,因为它似乎在一个错误的全局范围内。我尝试找到负责声明i的代码,但结果很麻烦(有很多代码和很多i)。

问题

获取说出

的控制台警告
  

创建全局变量“i”(main.js:342)

可能很有用。我该如何实现该功能?

研究

我认为每当创建新变量时我都需要某种事件。

  • 我们在JavaScript中有setters。但是,创建setter需要您提供属性名称。由于我想要监控所有属性,我无法真正使用它。
  • __noSuchMethod__MDN)会很完美但它只涵盖方法(并且没有__noSuchProperty__方法)。
  • Object.observeHTML5 Rocks)没有透露有关创建属性的代码的任何信息(console.trace()只给出了观察者函数的名称。)
  • Object.prototype.watchMDN) - 与设置者相同,您必须指定一个属性名称。
  • 每当创建新的全局变量时,调用Object.preventExtensions(window)MDN)会导致错误堆栈跟踪。此解决方案的问题在于它会干扰脚本执行并可能会更改其行为。它也不允许我捕获错误并正确格式化。

备注

  • 我知道jshint / jslint,我仍然认为在运行时中捕获这些声明可能很有用。
  • 我不太关心SO页面上的i变量那么多,您可以使用setter找到声明。我的问题涉及这个问题的一般解决方案。

3 个答案:

答案 0 :(得分:4)

IMO你有两个不错的选择:

  1. JS​​Hint。
  2. 严格模式。
  3. 当你泄漏全球时,两个人都会对你大喊大叫。严格的模式可能会更好地用于您的用例。

答案 1 :(得分:1)

你确实完成了你的作业,你想到了我想到的所有事情,正如你所发现的那样,它们都不合适。

我能想到的唯一方法就是监视全局对象(这个例子使用window作为全局对象:相应地修改Node或其他JavaScript容器)。这是一个监视新全局变量和删除全局变量的示例(如果您不需要监视删除,则可以删除该功能):

var globals = Object.keys(window);
var monitorGlobalInterval = 50;

setInterval(function(){
    var globalsNow = Object.keys(window);
    var newGlobals = globalsNow.filter(function(key){
        return globals.indexOf(key)===-1;
    });
    var deletedGlobals = globals.filter(function(key){
        return globalsNow.indexOf(key)===-1;
    });
    newGlobals.forEach(function(key){
        console.log('new global: ' + key);
    });
    deletedGlobals.forEach(function(key){
        console.log('global deleted: ' + key);
    });
    globals = globalsNow;
}, monitorGlobalInterval);

在此处查看此行动:http://jsfiddle.net/dRjP9/2/

答案 2 :(得分:0)

您可以尝试使用此方法获取已创建的全局变量列表:

(function(){
  var differences = {},
    ignoreList = (prompt('Ignore filter (comma sep)?', 'jQuery, Backbone, _, $').split(/,\s?/) || []),
    iframe = document.createElement('iframe'),
    count = 0; ignoreList.push('prop');

  for (prop in window) {
    differences[prop] = {
      type: typeof window[prop],
      val: window[prop]
    }; count++;
  }

  iframe.src = 'about:blank';
  iframe.style.display = 'none';
  document.body.appendChild(iframe);
  iframe = iframe.contentWindow || iframe.contentDocument;

  for (prop in differences) {
    if (prop in iframe || ignoreList.indexOf(prop) >= 0) {
      delete differences[prop];
      count--;
    }
  }

  console.info('Total globals: %d', count);
  return differences;
})();