Backbone 初始化时不保留属性值

Backbone not rest the property values when initialize

我刚刚发现 Backbone 在创建新实例时没有重置属性值(仅适用于对象和数组)。我创建了一个简单的 JSFiddle (http://jsfiddle.net/samitha/fb5chvbv/) 来演示这种行为。仔细观察后,发生这种情况是因为 backbone 处理原型链的方式。

tmpI: 0,
tmpO: {
    t: 0
},
tmpA: [0],

以下对象中的值在创建新实例时不会重置。第一次运行 I、O & A 将 = 0。当重新创建一个新实例时,值是 I = 0 但 O & A = 2。

这实际上不是Backbone.js的问题。

spinnerToggleFunctions: {}, //function () { return {} },
tmpI: 0,
tmpO: {
    t: 0
},
tmpA: [0]

您可能知道这一点,但是上面示例代码中的 tmpI,tmpO and tmpA 是 BaseView 的属性,这些属性将通过其实例中的 proto 进行访问。

当你

    this.tmpI = 1;
    this.tmpO.t = 1;
    this.tmpA[0] = 1;

您正在 this.tmpI 处创建新的实例 属性 所以现在实例有自己的 属性 命名为 tmpI 这意味着它不必检查是否 __proto__ 有一个 属性 叫做 tmpI

但是您调用 this.tmpO.t = 1;this.tmpA[0] = 1 的地方并没有创建实例的 属性,而是直接更改了 __proto__ 的 属性。

这都是因为你不能在 Array 或 Object 之前创建 Array 或 Object 成员 defined.to 避免这种情况,

    this.tmpI = "";
    this.tmpO = {};
    this.tmpA = [];
    this.tmpI = 1;
    this.tmpO.t = 1;
    this.tmpA[0] = 1;

现在您正在创建和更改实例 properties.prototype 属性 永远不会更改。

 init::BaseView
(index):46 *** I: 0 O: 0 A: 0
(index):59 *** I: 1 O: 1 A: 1
(index):33 init::BaseView
(index):46 *** I: 0 O: 0 A: 0
(index):59 *** I: 1 O: 1 A: 1

ofc 删除实例属性后,@tmpI、tmpO、tmpA 将再次指向原型属性。

preRender: function () {
    console.log('*** I: %o O: %o A: %o', this.tmpI, this.tmpO.t, this.tmpA[0]);
    this.tmpI = "";
    this.tmpO = {};
    this.tmpA = [];
    this.tmpI = 1;
    this.tmpO.t = 1;
    this.tmpA[0] = 1;
    delete this.tmpO;
    delete this.tmpA;
    delete this.tmpI;
    console.log('deleted instance propeties so these are prototype properties.  I: %o O: %o A: %o', this.tmpI, this.tmpO.t, this.tmpA[0]);
},

在 javascript 中,原型值在实例之间共享。 对象和数组是可变的,这意味着更改嵌套值将改变原型上的原始对象,并且不会将实例级别设置为 1。

长话短说,经验法则是在原型上设置方法,在实例级别上设置数据。

如果您想要唯一值,请在实例级别而不是原型上设置它们。

你需要的是这样的:

var BaseView = Backbone.View.extend({
    el: $('#root'),
    initialize: function () {
        console.log('init::BaseView');
        this.tmpI = 0
        this.tmpO = {t: 0}
        this.tmpA = [0],
    },
    baseViewMethod: function () {
        console.log('a base view method');
    },
    spinnerToggleFunctions: {}, //function () { return {} },

    preRender: function () {
        console.log('*** I: %o O: %o A: %o', this.tmpI, this.tmpO.t, this.tmpA[0]);
        this.tmpI = 1;
        this.tmpO.t = 1;
        this.tmpA[0] = 1;
        //this.spinnerToggleFunctions[new Date()]=1;
        //console.log('*** %o', this.spinnerToggleFunctions);
        //this.spinnerToggleFunctions={};
    },

    postRender: function () {
        console.log('*** I: %o O: %o A: %o', this.tmpI, this.tmpO.t, this.tmpA[0]);
        this.tmpI = 2;
        this.tmpO.t = 2;
        this.tmpA[0] = 2;
    },

    render: function () {
        this.preRender();
        this.$el.html("Time"+ new Date().toJSON());
        this.postRender();
    },
    destroy: function () {
        this.remove();
        this.unbind();
    }
});