【发布时间】:2015-02-12 13:19:39
【问题描述】:
我正在使用这个简单的 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>
我有一个指令,它只创建一个新的作用域,并且在它的模板中有另一个指令。
另一个指令做了一些奇怪的事情(我试图将问题缩小到导致泄漏的原因,这是我发现的重现问题的最短代码)。
在我的主 html 中,我只是使用简单的 ng-if 在无和 directive1 之间切换。
注意directive2 还在$scope 上创建了一个名为LeakObject 的新对象。我希望这个对象在我切换回空 div 时被垃圾收集,因为指令的范围应该消失,并且它上面的所有数据都随之消失,但是根据 Chrome 在隐身模式下的堆快照工具,它没有得到未分配。
我试图理解为什么会发生这种情况,以及为什么如果我注释掉 bar 方法中的语句,它不会发生。
重现步骤:
- 以隐身方式打开this file
- 打开开发工具并转到配置文件
- 刷新页面
- 点击
Toggle两次(现在您会再次在屏幕上看到Nothing) - 拍摄堆快照
- 在过滤器中写入“泄漏”,这样您就可以看到
LeakObject在不应该存在时仍然存在。
它应该是这样的:
有人可以帮忙/解释一下吗?
【问题讨论】:
-
显然,这在 Windows 8、Chrome 42 中不是问题
-
无法在 Ubuntu15/Chome 上重现问题
标签: javascript angularjs memory-leaks