Backbone.js模型中的数组本质上是静态的?

时间:2012-04-02 10:00:18

标签: backbone.js coffeescript

为什么Backbone.js模型中的数组本质上是静态变量?

class exports.Content extends Backbone.Model
    tags: []

然后如果我制作一些模型:

contentA = new Content()
contentB = new Content()

并为每个模型的数组添加一个字符串:

contentA.tags.push('hello')
contentB.tags.push('world')

他们最终都使用相同的数组:

contentB.tags // ['hello','world']

但如果它是一个字符串,则没有问题:

contentA.name = "c1"
contentB.name = "c2"

contentA.name // "c1"

4 个答案:

答案 0 :(得分:15)

简短回答

当您调用extends来定义对象时,您将新对象的配置作为对象文字传递。对象通过引用传递,extends函数仅将对tags数组的引用传递给新的类型定义。

正如其他人所说,您可以通过将tags分配给某个功能来纠正此问题。这是有效的,因为函数会延迟tags的求值,直到对象被实例化为止。 JavaScript中没有任何本机可以做到这一点,但它的Backbone本身将tags识别为函数或值。

答案很长

尽管您的代码在CoffeeScript中,但这归结为JavaScript中的一些组合:

  • JavaScript中没有类
  • 立即评估对象文字
  • JavaScript对象通过引用传递

在JavaScript中,没有类。期。 CoffeeScript为您提供了类的概念,但实际上,它被编译为没有类的JavaScript。

您可以拥有类型和类型定义(构造函数),但不能拥有类。 Backbone提供类似于类的定义,看起来类似于Java的“扩展”基于类的继承。但它仍然只是JavaScript,没有类。

相反,我们所拥有的是一个传递给extends方法的对象文字。就像你写这段代码一样:

var config = { tags: [] }

var MyModel = Backbone.Model.extends(config);

在此代码中,config是对象文字,或散列,键/值对或关联数组。无论你怎么称呼它,它都是同样的基本理念。最终得到的config对象具有tags属性。 config.tags的值是一个空数组[],它本身就是一个对象。

这让我们回到简短的回答:

当您调用extends来定义对象时,您将新对象的配置作为对象文字传递。对象通过引用传递,extends函数仅将对tags数组的引用传递给新的类型定义。

正如其他人所说,您可以通过将tags分配给某个功能来纠正此问题。这是有效的,因为函数会延迟tags的求值,直到对象被实例化为止。 JavaScript中没有任何本机可以做到这一点,但它的Backbone本身将tags识别为函数或值。

答案 1 :(得分:6)

“tags”正在Content.prototype上声明 - 它在所有Content实例中共享。您可能需要使用默认值:http://backbonejs.org/#Model-defaults。但是,应该注意的是,在定义默认值时必须使用函数(而不是散列),否则在使用通过引用传递的类型(例如数组)时仍会遇到同样的问题。

var Content = Backbone.Model.extend({
  defaults: function() { 
    return {
      tags: []
    };
  }
});

答案 2 :(得分:0)

benpickles在Backbone模型中是正确的,而在coffeescript中这样做的方法通常是在构造函数中初始化实例属性:

class Foo
  constructor: ->
    @bar = []

答案 3 :(得分:0)

正如Derick Bailey所说,通过引用传递是问题所在。我通过克隆数组来解决了这个问题(基本上是传递值):

var _events = window.active_model.get('events').slice(0);
_events.push({ key: "xxx", value: "yyy" });
window.active_field.set('events', _events);