为什么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"
答案 0 :(得分:15)
当您调用extends
来定义对象时,您将新对象的配置作为对象文字传递。对象通过引用传递,extends
函数仅将对tags数组的引用传递给新的类型定义。
正如其他人所说,您可以通过将tags
分配给某个功能来纠正此问题。这是有效的,因为函数会延迟tags
的求值,直到对象被实例化为止。 JavaScript中没有任何本机可以做到这一点,但它的Backbone本身将tags
识别为函数或值。
尽管您的代码在CoffeeScript中,但这归结为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);