为什么骨干.视图对象仍然保留在内存中

Why Backbone.View object still remains in memory?

本文关键字:保留 内存 视图 对象 为什么      更新时间:2023-09-26

我有一个显示对话框的简单视图。

Backbone.View.prototype.completeRemove = function(){
    this.undelegateEvents();
    this.remove();
    delete this.$el;
    delete this.el;
    console.log('completely removed')
}
MdApp.dialogBox = Backbone.View.extend({
    defaults: {
        text: __('No text provided'),
        buttonText: __('Ok'),
        callback: function(){
            return null;
        },
        el: $('#app-panel'),
        type: 'error',
        cancellable: false,
        cancelText: __('No'),
        picture: pic('default')
    },
    el: '<div class="dialog-box">',
    template: _.template($('#dialog-box-template').html()),
    events: {
        'click .confirm' : 'confirm',
        'click .cancel' : 'cancel'
    },
    initialize: function(){
        this.model = _.extend(this.defaults, this.model);
        this.render();
    },
    render: function(){
        var model = this.model;
        this.$el.html(this.template(model));
        model.el.append(this.el);
    },
    confirm: function(){
        var model = this.model;
        var view = this;
        this.completeRemove();
        model.callback();
    },
    cancel: function(){
        this.completeRemove();
    }
});

它有自己的默认值。每次初始化新对话框时,它的值在每次对话框调用之间都保持不变。例如,当我第一次调用对话框时:

new MdApp.dialogBox({model:{
        text: __('Do you really wanna delete this?'),
        buttonText: __('Unfortunately yes'),
        callback: function(){
            //some callback
        },
        cancellable: true,
        cancelText: __('No'),
        picture: pic('confirm delete')
    }});

之后,我调用另一个没有cancellable属性的对话框,所以它应该使用默认的(这是false),但它保持为真。这适用于所有其他性质。为什么会发生这种情况?

From the fine manual:

extend _.extend(destination, *sources)

复制对象中的所有属性到目标对象,并返回目标对象。

表示_.extend(o, ...)修饰o。当你这样做的时候:

this.model = _.extend(this.defaults, this.model);

你正在有效地这样做:

for(k in this.model)
    this.defaults[k] = this.model[k];
this.model = this.defaults;

defaults被附加到原型上,所以你实际上是在改变defaults,它将被MdApp.dialogBox的每个实例共享。这就是为什么你最终使用粘性属性:你将所有不同的this.model合并到视图原型的defaults中。

你可以这样做:

// Merge into an empty object to avoid altering this.defaults
this.model = _.extend({}, this.defaults, this.model);

或者你可以用_.defaults代替_.extend:

default _.defaults(object, *defaults)

default 对象中的值填充object中的null和undefined属性,并返回object。一旦属性被填充,其他默认值将不起作用。

你可以这样写:

_(this.model).defaults(this.defaults);

这将改变this.model的位置,所以你的视图将假设它完全拥有this.model,并且没有任何外部引用到该对象。