我在CoffeeScript中使用Backbone.js进行编程,并且在与lodash和merge函数相关的继承方面存在问题。
有一个超类
class NavigationView extends Backbone.View
config:
test:
string: "Test"
和从中派生的两个类
class SubView extends NavigationView
initialize: ->
# Setting the view's template property using the Underscore template method
_.merge @config, {
test:
string: "bla"
}
class IndexView extends NavigationView
...
如果我在SubView的函数内更改初始化配置变量,它也会在IndexView实例中更改。
我在BackBone.Router类中实例化我的对象:
index: () ->
# Instantiates a new view which will render the header text to the page
new IndexView()
sub: () ->
new SubView()
我创建了一个小提琴来展示它:http://jsfiddle.net/hijolan/9VeND/
任何想法如何做到这一点?
最好的问候,hijolan
答案 0 :(得分:4)
你的问题是_.merge
就地修改了它的第一个参数:
_.merge(object [, source1, source2, …])
将源对象的可枚举属性合并到
destination
对象中。
请注意,文档说destination
时,它的确意味着object
。 merge
的目的是成为_.extend
的深层版本,而Underscore文档明确指出会发生什么:
延伸
_.extend(destination, *sources)
将来源对象中的所有属性复制到目标对象,然后返回目标对象。
您会注意到lodash的extend
(AKA assign
)也会混淆参数名称:
_.assign(object [, source1, source2, …])
将
source
个对象的自己的可枚举属性分配给destination
对象。
当他们说object
时,他们的意思是destination
。
执行此操作时:
class NavigationView extends Backbone.View
config:
test:
string: "Test"
config
最终附加到NavigationView
的原型,因此config
及其子类将看到完全相同的NavigationView
对象。这意味着@config
中的config
是原型的initialize
:
_.merge @config, { test: { string1: "blub" } }
因此_.merge
会将新值合并到原型的config
中,并使更改一直显示到NavigationView
并进入所有子类。如果您追溯继承,您会发现该上下文中的@config
来自NavigationView
,因此您的_.merge
只是一种棘手且令人困惑的写作方式:
_.merge NavigationView::config, ...
问题的根源是_.extend
和_.merge
修改了他们的第一个参数。离开此陷阱的方法是提供可安全写入的目标对象:
@config = _.merge { }, @config, { test: { string1: 'blub' } }
# ----------------^^^