Backbone.js处理属性是数组

Kev*_*vin 35 javascript backbone.js

我真的很喜欢Backbone,但我最难做的事情看似简单.我感谢以下示例的任何帮助.

我有一个模型,标准,我想用来存储我的UI中的一些项目的状态.有一些简单属性,一个属性是一个ID数组,用于存储用户在UI中选择的标记的ID.

所以,我创建了一个新实例.我在tags数组中添加了一些项目.然后,我想重新开始,创建一个新实例,分配给同一个变量.但是,我的标签数组继续保存我作为第一个Criteria实例的一部分添加的信息.

我已经记录了下面的测试用例.

<!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>
Run Code Online (Sandbox Code Playgroud)

我在这里是不是很划算?我是否尝试使用Backbone来实现它的目的?或者我在javascript OO编程中遗漏了一些更通用的东西?

PS我最初使用Backbone标签集合,但是它提出了一系列不同的问题,这些问题与多个集合中引用的Tag模型有关,以及当从任何集合中删除项目时,Backbone的remove方法如何取消设置"集合"引用.另一天,另一个问题.

btf*_*ord 70

"默认值"也可以是一个函数.

var Criteria = Backbone.Model.extend({
    defaults: function () {
        return {
            "status": "Normal",
            "priority": "Normal",
            "tags": new Array()
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

这将在实例化新Criteria时创建新数组.请参阅:http://backbonejs.org/#Model-defaults

  • 关键是"defaults"属性现在是一个函数而不是一个对象.return表示从函数返回的对象,并用作"默认值"的值.正如其他人所解释的,如果"defaults"是一个对象,那么当创建一个新模型时,"defaults"中的每个属性都会被复制到该对象的属性中.当属性为字符串或数字时,这可以按预期工作,但对于对象和数组,此副本通过引用完成.对于每个具有自己的默认属性副本的实例,您应该使用一个函数. (10认同)
  • 我更喜欢这种语法,而不是所选答案中的语法 (7认同)
  • 请注意,您只需使用[]而不是"new Array()" (3认同)
  • 这是你应该这样做的方式."请记住,在JavaScript中,对象是通过引用传递的,因此如果将对象包含为默认值,它将在所有实例之间共享.相反,将默认值定义为函数." - http://backbonejs.org/#Model-defaults (3认同)

Der*_*ley 34

汤姆布莱克说的是为什么它保持阵列的相同值.解决此问题的一个选项是在初始化程序中设置默认值

        var Criteria = Backbone.Model.extend({

            defaults: {
                "status": "Normal",
                "priority": "Normal"
            },

            initialize: function(){
              if( !this.get('tags') ){ 
                this.set({tags: new Array()});
              }
            }

        });
Run Code Online (Sandbox Code Playgroud)

  • +1用于显示Backbone处理此方法的方式. (8认同)

Tam*_*ake 13

在"默认值"下定义"标记"时,您将创建一个新数组并将其设置为该类的默认值.然后,当您创建一个新实例时,它具有相同的Array引用,它仍然包含您推送到它的内容.

而不是为标签设置默认值,您应该能够[]在第一次使用它之前将其设置为:

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', []})
Run Code Online (Sandbox Code Playgroud)

  • 我最近在将Backs.Model类型类中的js Date对象存储为属性时遇到了同样的问题.我没有创建新的日期对象只是更改单个引用.因此,就骨干而言,日期从未改变,事件从未被解雇.规则与骨干一直将属性视为不可变值.如果需要更改属性克隆,则会创建一个新值,该值将创建新引用并更改新引用. (2认同)