Backbone.js处理属性的数组
我真的很喜欢Backbone,但是我最难做的事情似乎是简单的事情。 我感谢任何帮助下面的例子。
我有一个模型,标准,我想用来存储一些项目在我的用户界面的状态。 有几个简单的属性,一个属性是用于存储用户在UI中select的标签ID的ID数组。
所以,我创build了一个新的实例。 我添加一些项目到标签数组。 然后,我要开始新鲜的,创build一个新的实例,分配给相同的variables。 但是,我的标签数组继续保存我添加到其中的信息,作为Criteria的第一个实例的一部分。
我已经logging了下面的testing案例。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Test</title> <script src="Scripts/Libraries/jquery-1.6.1.js" type="text/javascript"></script> <script src="Scripts/Libraries/underscore.js" type="text/javascript"></script> <script src="Scripts/Libraries/backbone.js" type="text/javascript"></script> <script language="javascript" type="text/javascript"> $(function () { // Simple model to hold some state about my UI. var Criteria = Backbone.Model.extend({ defaults: { "status": "Normal", "priority": "Normal", "tags": new Array() } }); // Create new criteria. window.criteria = new Criteria(); // The length of the tags array should be 0. PASSES console.log("Expect 0: Actual " + window.criteria.get("tags").length); // Add a tag id to the tags array. window.criteria.get("tags").push(5); // Tag with ID of 5. // The length of the tags array should be 1. PASSES console.log("Expect 1: Actual " + window.criteria.get("tags").length); // Create a new instance of criteria. window.criteria = new Criteria(); // The length of the tags array should be 0. FAILS // CONFUSED. I thought this is now a new instance with a new set of attributes. // Why does the tags collection still have an item in it. console.log("Expect 0: Actual " + window.criteria.get("tags").length); // OK. So, I will call the clear method on the model. This is supposed to remove all attributes // from the model. // Then, I will create it again. window.criteria.clear(); window.criteria = new Criteria(); // The length of the tags array should be 0. FAILS. Still 1. console.log("Expect 0: Actual " + window.criteria.get("tags").length); // ARGH! console.log("HELP!"); }); </script> </head> <body> <h1>Test</h1> <p>Backbone test page.</p> </body> </html>
我只是在这里标记? 我是否试图使用骨干的事情是不是有意的? 或者我错过了一些更一般的JavaScript OO编程?
PS我最初使用Backbone标签集合,但是提出了一组完全不同的问题,涉及到在多个集合中引用标签模型,以及当从任何集合中删除某个项目时,Backbone的remove方法如何取消“集合”引用。 另一天,另一个问题。
汤姆布莱克是正确的,为什么它保持相同的值arrays。 解决这个问题的一个select是在初始化程序中设置默认值
var Criteria = Backbone.Model.extend({ defaults: { "status": "Normal", "priority": "Normal" }, initialize: function(){ if( !this.get('tags') ){ this.set({tags: new Array()}); } } });
“默认”也可以是一个function。
var Criteria = Backbone.Model.extend({ defaults: function () { return { "status": "Normal", "priority": "Normal", "tags": new Array() } } });
这将创build一个新的数组,当一个新的标准被实例化。 请参阅: http : //backbonejs.org/#Model-defaults
当您在“默认值”下定义“标签”时,您将创build一个新的数组并将其设置为该类的默认值。 然后,当你创build一个新的实例时,它有相同的数组引用,它仍然有你推入的东西。
而不是设置标签的默认值,您应该能够在第一次使用它之前将其设置为[]
:
window.criteria = new Criteria() window.criteria.set({'tags', []}) //you can use new Array() if you want window.criteria.get('tags').push(5) window.criteria = new Criteria() console.log(window.criteria.get('tags')) //should be undefined window.criteria.set({'tags', []})
要清楚的是,Maksym H.提供的最后一个选项不会解决问题。 提供了默认属性,假设所有的值都是不可变的。 然而,一个数组是可变的,这意味着它的值可以被改变(例如tags [0] =“hello”可以用tags [0] =“hi there”来改变)。
通过使用btford的答案,你迫使在模型的每个新实例上创build任何可变对象/属性的新实例,所以它永远不会共享,因为该对象是使用函数scopedvariables创build的。
同样,Derick Bailey的答案是正确的,它只是使用初始化方法而不是默认方法。