在销毁指令时是否需要销毁本地控制器变量?

时间:2016-03-29 01:24:14

标签: javascript angularjs angularjs-scope angular-directive

我最近一直在编写很多Angular指令,并且已经阅读过关于在销毁指令时必须手动删除你在指令中创建的内容。但它仍然有点不清楚。

我知道$ scope上的任何东西都被破坏了,但是在指令控制器中创建的局部变量,数组,函数等呢?

以下是我的应用

中的一些示例代码
angular.module('myModule').controller('s4pFileUploadCtrl', function($scope, $element, $attrs, FileUploader){

    var self = this;

    self.uploader = new FileUploader({
        settings: {}
    });

    // Elsewhere in the controller
    var reader = new FileReader();      
    reader.onload = onLoadFile;

    function onLoadFile(event) {
        var img = new Image();
        img.onload = onLoadImage;
    }

});

这是一个人为的,非常简化的功能,但是我需要在$ scope destroy事件中删除上传器吗?我是否需要对FileReader及其与onLoadFile事件相关的事情做些什么?

任何帮助将不胜感激。我已经阅读了很多关于清理指令的文章,但没有提到这样的事情。

2 个答案:

答案 0 :(得分:3)

这里有a great article更多关于javascript内存管理和垃圾收集的一些背景知识。基本上,它的工作原理是这样......

Javascript内存管理 - 垃圾收集器

创建时将为对象分配内存:

var o = {iThink: 'thereforeIAm'}; // memory allocated for an object and a string

然后,您可以从内存中读取console.log(o.iThink)'thereforeIAm'并将其打印到控制台。

如果您想创建一个新字符串并丢失{iThink: 'thereforeIAm'}对象的 need ,您可能决定覆盖o而不是引入新变量,例如:< / p>

o = 'helloImANewString';

幸运的是,引用(或缺少引用)在内部向javascript的垃圾收集器发送一条明确的消息,告知是否应该保留一段(有限)内存,或者释放它来执行其他任务。在这种情况下,对于先前为{iThink: 'thereforeIAm'}分配的对象和字符串没有引用,并且可以释放相应的内存(即&#34;垃圾收集&#34;)。

重要的是,请注意垃圾收集在内部进行。您不需要为此编写代码。您需要关注的是o的值,垃圾收集器可以推断需要,或多或少,来自剩余的引用

角度内存管理 - $ scope。$ destroy

不幸的是,javascript垃圾收集器无法根据单独的引用推断出与$scope删除相关的清除任务;需要额外的代码。

这是因为$ scope对象体现了一个比任何一个更复杂的概念。 javascript对象。特别是,当您的应用程序中没有用于某个$scope对象时,对于之前使用$$watchers方法注册的任何关联$scope.$watch,不得使用 并且还必须保留,以便儿童&#34; $scope个对象。 javascript垃圾收集器无法从简单的引用删除中推断出这种关系,例如:

$scope = null; // $scope object will be garbage collected, but nothing else

换句话说,必须告诉垃圾收集器该做什么,这正是$scope.$destroy method所做的。特别注意这些行:

$scope.$parent = $scope.$$nextSibling = $scope.$$prevSibling = $scope.$$childHead =
    $scope.$$childTail = $scope.$root = $scope.$$watchers = null;

现在回答你的问题

  

我知道放在$ scope上的任何内容都会被销毁,但是在指令控制器中创建的局部变量,数组,函数等呢?

是的,但不是直接通过$ destroy方法

调用函数时,为内部作用域对象分配的内存将仅保留分配给超出调用生命周期的引用范围。

在控制器的示例中,事实上,无论reader$scope还是$destroy,在运行控制器功能之后,都不会对$scope保留任何引用。但即使您像uploader那样将其附加到$scope.$destroy(),唯一剩下的参考资料也会因此附加到$ scope。因此,对uploader的任何调用都会删除对$scope的最后一次引用(通过删除对addEventListener的任何引用)并使其符合javascript垃圾回收的条件。

答案 1 :(得分:1)

执行$ scope。$ destroy()时,它将删除在$ scope上通过$ on注册的所有侦听器。

它不会删除DOM元素或任何附加的事件处理程序。

如果在元素上调用了element.remove(),那么它的所有子节点将从DOM中删除,并且所有事件处理程序都将通过element.on附加,但它不会破坏与该元素关联的$ scope。