在Coffeescript中使用mixins

3
我想通过使用mixin来拆分一个大类。
我正在使用Little Book中的这个mixin代码。
@include: (obj) ->
    for key, value of obj when key not in moduleKeywords
      # Assign properties to the prototype
      @::[key] = value

    obj.included?.apply(@)
    this

class FooMixin

  b: => @something = 2

class Foo extends Module
  @include FooMixin

  a: => @something = 1

问题在于FooMixin中的@FooMixin。我希望它变成Foo
我尝试在@include()的结尾添加_.bind(@::[key], @),但没有帮助。有什么建议吗?
1个回答

4

好的,我之前做错了几件事情。

1.

Little Book 中的 @include 需要一个对象而不是类。要让它与类一起使用,你需要写成 @include FooMixin::。然而,我现在已经开始使用对象了。

2.

当使用对象而不是类时,fat arrow 会在 CoffeeScript 包装器的顶部添加一行代码 _this = this。所有方法都绑定到全局上下文中,这并不是我们想要的。为了修复它,我们必须将 fat arrows 转换为 thin arrows,并将每个函数绑定到我们的 Foo 实例上。使用 Underscore,我将这个功能添加到 Foo 的构造函数中:

constructor: ->
  for fname in _.functions FooMixin
    @[fname] = _.bind @[fname], @
  super

我尝试了_.bindAll @, _.functions FooMixin,但是它给我一个错误,说类似于在Function.bind中无法运行未定义的绑定。奇怪的错误,因为上面的代码几乎与_.bindAll方法相同。
所以现在我可以将我的类分开以获得更好的可读性和代码共享。
更新: _.bindAll的问题在于它需要一个splat而不是一个数组。修复方法是使用_.bindAll @, _.functions(FooMixin)...更新: 找到了更好的解决方案。
与原始帖子相同。使用类作为混合物。
使用@include FooMixin::或更改@include以在原型而非属性上操作。
Foo构造函数中编写FooMixin.call @,这样可以正确地绑定方法。
这很有效并且很干净。
唯一可能的问题是混合物将被现有属性覆盖。我能想到的唯一解决方法是做一些像这样的事情:
after = ->
  _.extend Foo, FooMixin::

class Foo
   # define...

after()

或者将扩展方法传递给 _.defer,但这样做很繁琐,可能不起作用。


对于那些可能正在使用backbone.js(或underscore.js)的人,需要额外注意的是,模型上已经定义了一个名为extend的方法,这将与此处描述的方法冲突。如果你发现自己遇到了各种问题,请尝试将其重命名为其他名称--这对我很有效。 - Chris Salzberg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接