2012-10-11 68 views
3

我想通過使用mixin拆分一個大類。在Coffeescript中使用mixins

我用這混入代碼從Little Book

@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 

問題是,在@是​​​​。我希望它是Foo

我曾嘗試在@include()的末尾添加_.bind(@::[key], @)行,但它沒有幫助。有什麼建議麼?

回答

3

好吧,我做錯了一些事情。

1.

@include從小書需要對象不是類。爲了讓它與課程一起工作,您需要編寫@include FooMixin::。不過,我從此開始使用對象。

2.

當使用對象,而不是一類,脂肪右箭頭在其讀取_this = this頂部添加CoffeeScript的包裝器中的線。所有方法都綁定到全局上下文,而這並不是我們想要的。要修復,我們必須將胖箭頭轉換爲細箭頭,並將每個函數綁定到我們的Foo實例。使用下劃線我已將此添加的Foo構造:

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

我試圖_.bindAll @, _.functions FooMixin,但它給了我一個錯誤說像At Function.bind, could not run bind of undefined.奇怪的錯誤,看到上面的代碼是幾乎等同於_.bindAll方法。

所以,現在我可以將我的課程拆分爲更好的可讀性和代碼共享。


UPDATE:與_.bindAll的問題是,它需要一個圖示不是一個數組。修正是使用_.bindAll @, _.functions(FooMixin)...

更新:找到了更好的解決方案。

與原文相同。爲mixin使用類。

使用@include FooMixin::或更改@include來操作原型而不是屬性。

Foo構造函數中編寫FooMixin.call @它正確地綁定了這些方法。

這工作得很好,很乾淨。

唯一的潛在問題是mixin將被現有屬性覆蓋。要解決這個問題,我可以看到的唯一方法是做這樣的事情:

after = -> 
    _.extend Foo, FooMixin:: 

class Foo 
    # define... 

after() 

或者通過擴展方法_.defer但這是如此哈克,可能將無法正常工作。

+0

對於任何可能使用backbone.js(或underscore.js)的人來說,已經有一個方法在模型上定義了一個名爲['extend'](http://backbonejs.org/#Model-extend)的方法這將與這裏描述的相沖突。如果你發現你遇到了各種各樣的問題,請嘗試將它重命名爲其他內容 - 這對我有用。 –