Javascript 主干视图属性:一个在实例上,一个在原型上?

Javascript 主干视图属性:一个在实例上,一个在原型上?,javascript,inheritance,backbone.js,prototype,Javascript,Inheritance,Backbone.js,Prototype,是的,这个标题没有多大意义 我有一个观点。此视图创建子视图。这些子视图存储在一个数组中,因此我可以在某个时候删除它们 MN.ContactsView = MN.BaseView.extend ({ tagName : "div", contactViewItems : [], initialize : function(){ this.listenTo(MN.client.contacts, "add", this.addOne); this.listenT

是的,这个标题没有多大意义

我有一个观点。此视图创建子视图。这些子视图存储在一个数组中,因此我可以在某个时候删除它们

MN.ContactsView = MN.BaseView.extend ({

tagName : "div",

contactViewItems : [],

initialize : function(){        
    this.listenTo(MN.client.contacts, "add", this.addOne);
    this.listenTo(MN.client.contacts, "reset", this.addAll);
    this.listenTo(MN.client.contacts, "all", this.render);      
    MN.client.contacts.fetch();

},  render: function(){

},

addOne : function($contactModel){       
    var view = new MN.ContactsViewItem({model: $contactModel});
    this.contactViewItems.push(view);
    $("#contactsContainer").append(view.render().el);

},

addAll : function(){
    MN.client.contacts.each(this.addOne, this)
},

close : function(){

},

destroy: function(){
    for(var i =0; i < this.contactViewItems.length; i++) this.contactViewItems[i].destroy();
    this.contactViewItems = [];
    debugger;
    console.log("Length: " + this.contactViewItems.length );
    MN.BaseView.prototype.destroy.call(this);   
},
MN.ContactsView=MN.BaseView.extend({
标记名:“div”,
contactViewItems:[],
初始化:函数(){
this.listenTo(MN.client.contacts,“add”,this.addOne);
this.listenTo(MN.client.contacts,“reset”,this.addAll);
this.listenTo(MN.client.contacts,“all”,this.render);
MN.client.contacts.fetch();
},render:function(){
},
addOne:函数($contactModel){
var view=newmn.ContactsViewItem({model:$contactModel});
点击.contactViewItems.push(查看);
$(“#contactsContainer”).append(view.render().el);
},
addAll:function(){
MN.client.contacts.each(this.addOne,this)
},
关闭:函数(){
},
销毁:函数(){
对于(var i=0;i
当我销毁视图并检查调试器时,我会看到同一个变量两次


当您使用
extend
方法创建类时,您提供的属性将放在原型中。这意味着,它们将由类的所有实例共享。如果您在某些实例中碰巧更改了该属性的值,您将对原型进行阴影处理,以便该属性具有一个新的属性w值,不再与原型链接

所以,这里发生的事情如下:

当您使用
this.contactViewItems.push(view);
修改
contactViewItems
时,您不会更改存储在原型中的值。相反,您会更改该值所指向的对象。因此,您仍然在修改一个数组,该数组由类的所有实例共享

但是,当您执行
this.contactViewItems=[];
时,您实际上是在更改值,因为您正在为它提供一个全新的对象。此时,您只需将您的类的原型(尤其是该实例的原型)阴影化即可。原型当然仍然存在(您没有对它做任何操作),因此您将看到该属性两次


现在,它肯定没有按你希望的那样工作,我相信你现在知道了问题的核心,可以想出几种解决方案(我不知道你的应用程序的细节,所以没有更多细节我帮不了你).

当您使用
extend
方法创建类时,您提供的属性将放在原型中。这意味着,它们将由类的所有实例共享。如果您碰巧在某些实例中更改了该属性的值,您将对原型进行阴影处理,以便该属性具有新的属性值,不再与原型链接

所以,这里发生的事情如下:

当您使用
this.contactViewItems.push(view);
修改
contactViewItems
时,您不会更改存储在原型中的值。相反,您会更改该值所指向的对象。因此,您仍然在修改一个数组,该数组由类的所有实例共享

但是,当您执行
this.contactViewItems=[];
时,您实际上是在更改值,因为您正在为它提供一个全新的对象。此时,您只需将您的类的原型(尤其是该实例的原型)阴影化即可。原型当然仍然存在(您没有对它做任何操作),因此您将看到该属性两次

现在,它肯定不是你想要的那样工作,我相信你现在知道了问题的核心,可以想出几种解决方案(我不知道你的应用程序的细节,所以没有更多细节我帮不了你)

当我销毁视图并检查调试器时,我会看到相同的变量两次

因为您已经在
destroy
函数中的实例上第二次创建了它:

this.contactViewItems = [];
如果您想清除原型上的阵列,您应该使用

MN.ContactsView.prototype.contactViewItems = [];

当我销毁视图并检查调试器时,我会看到相同的变量两次

因为您已经在
destroy
函数中的实例上第二次创建了它:

this.contactViewItems = [];
如果您想清除原型上的阵列,您应该使用

MN.ContactsView.prototype.contactViewItems = [];


正如Loamhoof指出的,问题在于contactViewItems是ContactsView原型的属性

修改视图以使其按照您可能期望的方式运行的一种简单方法是,不要使用空数组初始化contactViewItems。而是在初始化中创建空数组

例如:

MN.ContactsView = MN.BaseView.extend ({

tagName : "div",

contactViewItems : null,

initialize : function(){        
    this.contactViewItems = [];
    this.listenTo(MN.client.contacts, "add", this.addOne);
    this.listenTo(MN.client.contacts, "reset", this.addAll);
    this.listenTo(MN.client.contacts, "all", this.render);      
    MN.client.contacts.fetch();
},  

现在,向this.contactViewItems添加项目直接在视图对象上(在本例中,您可能需要这样做),而原型包含的contactViewItems为空。

正如Loamhoof指出的,问题在于contactViewItems是ContactsView原型的属性

修改视图以使其按照您可能期望的方式运行的一种简单方法是,不要使用空数组初始化contactViewItems。而是在初始化中创建空数组

例如:

MN.ContactsView = MN.BaseView.extend ({

tagName : "div",

contactViewItems : null,

initialize : function(){        
    this.contactViewItems = [];
    this.listenTo(MN.client.contacts, "add", this.addOne);
    this.listenTo(MN.client.contacts, "reset", this.addAll);
    this.listenTo(MN.client.contacts, "all", this.render);      
    MN.client.contacts.fetch();
},  
现在,向this.contactViewItems添加项目直接在视图对象上(在本例中,您可能需要这样做),而原型包含一个为null的contactViewItems