由于lodash合并功能,CoffesScript中的继承无法正常工作

时间:2013-01-04 18:51:07

标签: inheritance backbone.js coffeescript lodash

我在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

1 个答案:

答案 0 :(得分:4)

你的问题是_.merge就地修改了它的第一个参数:

  

_.merge(object [, source1, source2, …])

     

将源对象的可枚举属性合并到destination对象中。

请注意,文档说destination时,它的确意味着objectmerge的目的是成为_.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' } }
# ----------------^^^

演示:http://jsfiddle.net/ambiguous/7j2FM/