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();
}
});
我刚刚发现 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();
}
});