JavaScript 遍历所有现有对象以查找对象键

JavaScript loop through all existing objects to find an object key

我正在尝试调试由其他人构建的系统。我有一个缩小的库,它对外部数据源进行 ajax (xhr) 调用,并将接收到的数据写入对象或变量。该调用是在页面加载后立即进行的,因此我无法通过附加一个函数来注册所有 XHR 调用请求来捕获它。所以我试图 运行 遍历浏览器 window 拥有的所有变量和对象。我正在尝试这个:

var foundVar = false;
loopThroughObject(this);

function loopThroughObject(obj) {
  if (!foundVar) {
    try {
      for (var name in obj) {
        if (obj[name] && {}.toString.call(obj[name]) === '[object Function]') { //making sure that the object is not a function 
        } else {
          if (name == 'searchedKey') { //found the object with key = searchedKey
            console.log(obj[name]);
            foundVar = true;
          } else {
            setTimeout(loopThroughObject.bind(null, obj[name]), 10); //do more recursion of inner objects
          }
        }
      }
    } catch (error) {}
  }
}

问题是setTimeout(loopThroughObject.bind(null, obj[name]), 0);部分堆叠起来,出现内存问题。我尝试了简单的 loopThroughObject(obj[name]),但在 25000 次循环后我遇到了“太多递归”错误。似乎我还遗漏了一些东西,它导致循环遍历一些我不需要的对象类型。有谁知道更有效的循环方式吗?

P.S。我尝试了一个非常简单的 HTML 页面,代码工作正常:

<html>
<head>
<script>
    var test = JSON.parse("{\"searchedKey\":\"12\"}");
    </script>
</head>
<body>
</body>
</html>

问题几乎可以肯定是 window 有几个指向自身的属性,因此您的代码将进入无限循环。很可能还有其他循环引用。

您可以使用 Set 记住您已经查看过的对象,就像这样(我还添加了一些其他调整;例如,您可以使用 [=13 检查函数=]):

let foundVar = false;
let seen = new Set();
loopThroughObject(this);

function loopThroughObject(obj) {
    if (!foundVar) {
        try {
            for (const name in obj) {
                const value = obj[name];
                if (typeof value !== "function") {
                    if (name == "searchedKey") { // found the object with key = searchedKey
                        console.log(value);
                        foundVar = true;
                        break;
                    } else if (value && typeof value === "object" && !seen.has(value)) {
                        seen.add(value);
                        loopThroughObject(value); // No need for setTimeout
                    }
                }
            }
        } catch (error) {}
    }
}