2

我在 CoffeeScript 中使用 Backbone.js 进行编程,并且在与 lodash 和合并函数相关的继承方面存在问题。

有一个超类

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

4

1 回答 1

4

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

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

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

请注意,文档所说的destination真正意味着object. 的目的merge是成为一个深度版本,_.extend并且下划线文档明确说明了会发生什么:

延长 _.extend(destination, *sources)

将源对象中的所有属性复制到目标对象,然后返回目标对象。

您会注意到 lodash 的extend(AKA assign)也会混淆参数名称:

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

将对象自己的可枚举属性分配sourcedestination对象。

object当他们说的时候,他们的意思是destination

当你这样做时:

class NavigationView extends Backbone.View
  config:
    test:
      string: "Test"

最终config附加到原型上NavigationView,因此完全相同的config对象将被NavigationView其子类看到。这意味着这@configconfig您的原型initialize

_.merge @config, { test: { string1: "blub" } }

所以_.merge会将新值合并到原型中config,这使得更改一直可见到NavigationView它的所有子类。如果你追溯继承,你会发现@config在那个上下文中是 fromNavigationView所以你_.merge只是一种棘手和令人困惑的写作方式:

_.merge NavigationView::config, ...

问题的根源在于_.extend_.merge修改了他们的第一个论点。摆脱这个陷阱的方法是提供一个可安全写入的目标对象:

@config = _.merge { }, @config, { test: { string1: 'blub' } }
# ----------------^^^

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

于 2013-01-04T22:40:13.043 回答