【问题标题】:Inheritance in CoffesScript doesn't correctly work because of lodash merge function由于 lodash 合并功能,CoffesScript 中的继承无法正常工作
【发布时间】:2013-01-04 18:51:07
【问题描述】:

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

【问题讨论】:

  • 您还有其他未向我们展示的内容。您的代码与this example 有何不同?您可能想检查最后一个代码块中的缩进,正确的缩进在 CoffeeScript 中非常重要。
  • 嘿!你是绝对正确的......我使用 _.merge 来自 lodash 的函数(如 underscore.js)在我的初始化函数中合并配置以合并父配置和派生类中的配置......在将其替换为整个配置未合并(仅用于测试目的)它工作正常!感谢您的帮助...
  • 以下小提琴显示了问题:jsfiddle.net/hijolan/9VeND

标签: inheritance backbone.js coffeescript lodash


【解决方案1】:

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

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

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

请注意,文档中提到的destination 的真正含义是objectmerge 的意图是成为 _.extend 的深层版本,Underscore 文档明确说明了会发生什么:

扩展 _.extend(destination, *sources)

source 对象中的所有属性复制到 destination 对象,并返回 destination 对象。

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

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

source 对象自己的可枚举属性分配给destination 对象。

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

当你这样做时:

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

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

_.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/

【讨论】:

  • 嘿!非常感谢!一方面是(简单的)解决方案,另一方面是完美而深刻的;)解释!!!!!!!
  • 如果我不能解释那就是我不明白,如果我不明白那我就无法回答:) 我不明白为什么每个人的extend 行为这种方式(甚至 jQuery 的$.extend)做到了,对我来说似乎很容易出错,而且“容易出错”不应该是默认行为。我想借口是表现。
猜你喜欢
  • 2021-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-19
  • 2019-12-29
  • 2017-09-23
  • 1970-01-01
相关资源
最近更新 更多