检测大型JS程序中的任何变量何时设置为NaN

dum*_*ter 5 javascript debugging nan

我有一个庞大,凌乱的JS代码库.有时,在使用应用程序时,变量设置为NaN.由于x = 2 + NaN结果x被设定为NaN,NaN以病毒传播.在某种程度上,在它传播到很远之后,用户注意到整个地方都有NaN,并且狗屎通常不再起作用.从这种状态来看,我很难回溯并识别NaN的来源(并且很可能有多个来源).

NaN bug也不容易重现.尽管有数百人观察并报告给我,但没有人能告诉我一系列导致NaN出现的步骤.也许这是一种罕见的竞争条件.但它绝对是罕见的,而且起源不确定.

我该如何解决这个错误?有任何想法吗?

我想到的两个愚蠢的想法,这可能是不可行的:

  1. 编写某种预处理器,isNaN在每次使用任何变量之前插入检查并记录第一次出现的NaN.我不认为以前这样做过,我不知道会有多难.任何意见,将不胜感激.

  2. 在JS引擎中运行我的代码,该引擎能够在任何变量设置为NaN时设置断点.我认为没有任何东西可以开箱即用,但将它添加到Firefox或Chrome有多难?

我觉得我不应该是第一个遇到这类问题的人,但我找不到其他人在谈论它.

Kor*_*Den 1

如果您做得很好,使事物远离全局名称空间并将事物嵌套在对象中,这可能会有所帮助。我将在序言中说,这绝不是一个完全完整的解决方案,但至少,这应该对您的搜索有所帮助。

function deepNaNWatch(objectToWatch) {
  'use strict';

  // Setting this to true will check object literals for NaN
  // For example: obj.example = { myVar : NaN };
  // This will, however, cost even more performance
  var configCheckObjectLiterals = true;

  var observeAllChildren = function observeAllChildren(parentObject) {

    for (var key in parentObject) {
      if (parentObject.hasOwnProperty(key)) {
        var childObject = parentObject[key];

        examineObject(childObject);
      }
    }
  };

  var examineObject = function examineObject(obj) {
    var objectType = typeof obj;

    if (objectType === 'object' || objectType === 'function') {
      Object.observe(obj, recursiveWatcher);
      if (configCheckObjectLiterals) {
        observeAllChildren(obj);
      }
    } if (objectType === 'number' && isNaN(obj)) {
      console.log('A wild NaN appears!');
    }
  };

  var recursiveWatcher = function recursiveWatcher(changes) {
    var changeInfo = changes[0];
    var changedObject = changeInfo.object[changeInfo.name];

    examineObject(changedObject);
  };

  Object.observe(objectToWatch, recursiveWatcher);
}
Run Code Online (Sandbox Code Playgroud)

deepNaNWatch(parentObject)一旦创建它们,就调用您用来嵌套的每个顶级对象/函数。任何时候在被监视的对象/函数中创建对象或函数时,它本身也将被监视。任何时候number在监视对象下创建或更改 a 时(记住这一点),typeof NaN == 'number'它都会检查它是否为 NaN,如果是,则运行 处的代码console.log('A wild NaN appears!');。请务必将其更改为您认为有帮助的任何类型的调试输出。

如果有人能找到一种方法将其强制到全局对象上,这个函数会更有帮助,但我所做的每一次尝试都只是告诉我,我应该停下来思考我所做的事情。

哦,如果从上面看还不是很明显,那么在大型项目中,这个功能必然会让“速度”和“效率”等讨厌的功能成为过去。