我做了一个指令,当点击它时,会创建一个使用jQuery附加到正文的对话框。问题是当关闭对话框时,范围永远不会被正确清理。如下图所示167 ChildScopes被保留。这与对话框中包含ng-repeat指令的项目数相匹配。
我试图在Plnkr上创建一个极其简单的场景版本。令我惊讶的是,实际上,在Plnkr的每个关闭处都移除了范围。因此,即使在调用$destroy
之后,生产中的某个地方也会导致范围保持活跃状态。
link: ($scope, $element, $attr) ->
$element.on 'click', () ->
$scope.$apply () ->
child = $scope.$new()
template = """<span ng-controller="ListCtrl">...List dialog things...</span>"""
compiledTemplate = $compile(template)(child)
container = containers.createDialogContainer($element)
container.append(compiledTemplate)
#cleanup
$scope.closeWidget = () ->
container.trigger("container_close")
return
container.on "container_close", ()->
child.$apply () ->
child.$destroy()
return
所以这是我的问题:
即使在调用$ destroy,触发和执行垃圾收集后,什么可以导致范围保持活动?
由于显而易见的原因,我无法向您展示我们的生产代码。然而,Plnkr中的指令与我的调试充分匹配。
答案 0 :(得分:5)
通常,如果另一个JS对象仍然可以访问GC,则无法清除作用域(或任何其他JS对象)。
实际上,在同样使用JQuery的Angular项目中,这很可能是由:
引起的例如,您的示例会造成内存泄漏。
从你的代码:
$scope.removeDialog = () ->
console.log "closing"
child.$destroy()
$('.listshell').remove()
return
您没有将child
设置为null
,因此$scope.removeDialog
仍然可以访问child
变量引用的范围对象。因此,此对象不能用于GC。
注意:在我看来,将removeDialog
放在子范围上会更合适。现在,您的示例仅起作用,因为子范围未被隔离。
答案 1 :(得分:0)
关闭函数可以使函数激活对象在范围被“销毁”后仍然保持活动状态。例如,您可能还有内部函数仍然在您试图销毁其范围的函数中引用变量对象。
使引用变量无效将是最佳选择,而不是删除
答案 2 :(得分:0)
我唯一能想到的是,如果某个地方的控制器或指令之外的某个全局函数或函数引用了该指令范围内的方法,那么它将使该范围保持活动状态。应用