【问题标题】:parentNode being lost on Javascript inner closure? Chrome bug?parentNode 在 Javascript 内部闭包中丢失?铬错误?
【发布时间】:2016-06-24 11:35:27
【问题描述】:

当我在 Chrome 中执行以下测试 HTML 页面时,我在调试控制台中看到以下内容:

Has parent? true
Has parent? false

我是否认为这是一个 Chrome 错误(它不会在其他浏览器中发生),或者 Chrome 是否出于某种原因有权这样做?它导致我的一个网络应用程序出现错误,我最终隔离了这个 sn-p 以重现核心问题。

这里是测试页面:

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="UTF-8">
    <title></title>
  </head>
  <body class="">
      
      
      <script>
        function testDoodle() {
          var testParentEl = document.createElement('div');
          var testChildEl  = testParentEl.appendChild(document.createElement('div'));
          
          document.body.innerHTML+=('Has parent? ' + !!testChildEl.parentNode+'<br>');
          console.log('Has parent? ' + !!testChildEl.parentNode);
          
          setTimeout(function() {
              document.body.innerHTML+=('Has parent? ' + !!testChildEl.parentNode+'<br>');
              console.log('Has parent? ' + !!testChildEl.parentNode);
          },
          2000);
          return;
        }
        testDoodle();
      </script>

  </body>
</html>

编辑:我应该提到我正在使用 Chrome 49.0.2623.87 m(64 位)在 Windows 7 上进行测试。还能够使用 Chrome 49 在 OSX 10.11.2 上重现。

另外,我应该提一下,有时它会显示真/真,有时会显示真/假。您可能需要重新加载页面几次才能看到问题。我不确定,但调试工具(控制台)可能也需要打开。

非常感谢。

【问题讨论】:

  • 在 Chrome 48 OSX 中为我工作
  • 我无法复制 (Chrome 48.0.2564.109)。您确定 testParentEl 在调用之间没有发生变异吗?
  • 我应该提到我正在使用 Chrome 49.0.2623.87 m(64 位)在 Windows 7 上进行测试。另外,我应该提一下,有时它会显示真/真,有时会显示真/假。您可能需要重新加载页面几次才能看到问题。我不确定,但调试工具(控制台)可能也需要打开。
  • 在相同的浏览器版本(Windows 10)上对我来说同样的问题
  • 已更新至 Chrome 49 仍无法重现。

标签: javascript html google-chrome garbage-collection closures


【解决方案1】:

我的猜测是testChildEl.parentNode 没有强烈引用testParentEl,所以它被垃圾收集了。

在超时内引用 testParentEl 并在 testChildEl 上添加对 testParentEl 的强引用为我解决了问题:

(function testDoodle() {
  var testParentEl = document.createElement('div');
  var testChildEl  = testParentEl.appendChild(document.createElement('div'));
  setTimeout(function() {
    testParentEl; // Prevents it from being garbage collected
    document.write('Has parent? ' + !!testChildEl.parentNode);
  }, 100);
})();

(function testDoodle() {
  var testParentEl = document.createElement('div');
  var testChildEl  = testParentEl.appendChild(document.createElement('div'));
  testChildEl.strongParent = testParentEl; // Prevents garbage collection
  setTimeout(function() {
    document.write('Has parent? ' + !!testChildEl.parentNode);
  }, 100);
})();

【讨论】:

  • 这对我来说真的是个错误。
  • Javascript 中是否已经存在诸如“强”和“弱”引用之类的东西?我的理解是没有。我也发现问题可以通过在闭包中明确引用 testPartEl 来解决。是的,我确信这是一个错误。显然,一些 Chrome 优化变坏了。我只是不确定为什么似乎没有其他人被它所困扰。
  • @logidelic ES6 引入了 WeakSets 和 WeakMaps,它们存储了对对象的弱引用。除此之外,它完全依赖于实现,规范不需要垃圾收集器。 bu定义,应该无法检测到一个对象是否已经被垃圾收集器,所以这是一个bug。
【解决方案2】:

我相信 Chrome v50 最终解决了这个问题(或者至少我在更新后无法重现)。

【讨论】:

    猜你喜欢
    • 2016-09-02
    • 2016-06-02
    • 1970-01-01
    • 2014-06-22
    • 2021-07-13
    • 1970-01-01
    • 2016-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多