Angular指令内存泄漏?

Bar*_*ash 15 javascript memory-leaks angularjs

我正在使用这个简单的html文件来重现我发现的内存泄漏:

<!doctype html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.6/angular.min.js"></script>
        <script>
            var app = angular.module('testApp', []);

            app.directive('directive1', function() {
                return {
                    template: '<div directive2></div>',
                    scope: true
                };
            });

            app.directive('directive2', function () {
                function LeakObject() {}

                function Foo() {
                    this.bar = function($scope) {
                            $scope.nottheredude;
                    };
                }

                return {
                    scope: true,
                    link: function($scope) {
                            $scope.memoryThatLeaks = new LeakObject();

                            new Foo().bar({});
                            new Foo().bar($scope);
                    }
                };
            });
        </script>
    </head>
    <body ng-app="testApp">
        <button ng-click="show = !show">Toggle</button>
        <div ng-if="show">The directive <div directive1></div></div>
        <div ng-if="!show">Nothing</div>
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)

我有一个指令,只创建一个新的范围,并在其模板中有另一个指令.

另一个指令做了一些有点奇怪的事情(我试图将问题缩小到导致泄漏的问题,这是我发现的最短代码再现问题).

在我的主要HTML中,我只是在没有任何东西和directive1简单的东西之间切换ng-if.

请注意,directive2还会在被$scope调用者上创建一个新对象LeakObject.我希望这个对象在我切换回无div时被垃圾收集,因为该指令的范围应该消失并且所有数据都随之消失,但根据Chrome的隐身模式下的堆快照工具,它没有得到未分配.

我试图理解为什么会发生这种情况,以及为什么,如果我在bar方法中注释掉语句,它就不会发生.

重现步骤:

  1. 以隐身方式打开此文件
  2. 打开开发工具并转到"个人档案"
  3. 刷新页面
  4. 点击Toggle两次(现在Nothing再次在屏幕上看到)
  5. 拍摄快照
  6. 在过滤器中写入"泄漏",这样您就可以看到它在LeakObject不存在时仍然存在.

它应该是这样的:

问题

有人可以帮忙/解释一下吗?

Mor*_*man 2

一切都按预期工作,按照您的步骤操作后,我在快照中没有看到任何泄漏对象。

您可以将以下代码添加到链接函数中以查看该指令实际上正在被销毁

控制器和指令在被销毁之前发出一个事件。在这里您有机会拆除插件和侦听器并执行垃圾收集。订阅 $scope.$on('$destroy', ...) 事件

$scope.$on('$destroy',function(){
  //$scope.memoryThatLeaks = null;
  alert('!');
 });
Run Code Online (Sandbox Code Playgroud)

  • 传递给 `$on('$destroy'` 的函数被执行这一事实并不能真正证明该指令正在被“销毁”,也不能证明不存在内存泄漏。不过,并不是说存在内存泄漏,我自己还没有研究过。 (5认同)