0

私は現在Backbone.jsでPeepCodeビデオを処理していますが、すべてを裸のJavaScriptではなくCoffeeScriptで書き込もうとしています。

これまでのところ、コードでJasmineテストを実行しようとした場合を除いて、いくつかのTypeErrorsが発生しました。

TypeError: Cannot call method 'isFirstTrack' of undefined
TypeError: Cannot call method 'get' of undefined

私のCoffeeScript/Backboneファイルは次のようになります。

jQuery ->
  class window.Album extends Backbone.Model
    isFirstTrack: (index) ->
    index is 0

  class window.AlbumView extends Backbone.View
    tagName:    'li'
    className:  'album'

    initialize: ->
      @model.bind('change', @render)
      @template = _.template $('#album-template').html()     
    render: =>
      renderedContent = @template @model.toJSON()
      $(@el).html(renderedContent)
      return this

そして、このようなジャスミンのテスト仕様:

var albumData = [{
  "title":  "Album A",
  "artist": "Artist A",
  "tracks": [
    {
        "title": "Track A",
        "url": "/music/Album A Track A.mp3"
    },
    {
        "title": "Track B",
        "url": "/music/Album A Track B.mp3"
    }]
}, {
  "title": "Album B",
  "artist": "Artist B",
  "tracks": [
    {
        "title": "Track A",
        "url": "/music/Album B Track A.mp3"
    },
    {
        "title": "Track B",
        "url": "/music/Album B Track B.mp3"
  }]
}];

describe("Album", function () {

  beforeEach(function () {
    album = new Album(albumData[0]);
  });

  it("creates from data", function () {
    expect(this.album.get('tracks').length).toEqual(2);
  });

  describe("first track", function() {
    it("identifies correct first track", function() {
      expect(this.album.isFirstTrack(0)).toBeTruthy();
    })
  });

});

この問題は、CoffeeScriptがすべてを関数でラップすることに関係していると思います。方程式からjQueryを削除すると、正常に機能します。不思議なことに、Jasmineは、ページのコンソールでTypeError: Cannot call method 'isFirstTrack' of undefined実行すると返されるので、ウィンドウが変数とメソッドにアクセスできるかどうかを教えてくれます。album.isFirstTrack(0)true

4

2 に答える 2

2

理由はスコーピングです、はい。

albumキーワードなしで、別のオブジェクトにアタッチせずに変数を宣言するvarと、グローバルスコープで変数が作成されます。

これは悪い考えです。作成するグローバルオブジェクトの数を本当に制限したいのは、JavaScriptの別のチャンクがデータを上書きしたり、競合を引き起こしたりするのが簡単だからです。

この観点から、テストを呼び出すというあなたの考えthis.modelは正しいです。問題は、それを実行できるようにするためにアタッチする必要があるということmodelですthis。簡単:

  beforeEach(function () {
    this.album = new Album(albumData[0]);
  });

あなたがしなければならないのは言うことだけでthis.album = ...あり、あなたは終わりです。これで、テストで検出できるようになりthis.album、すべてが機能するはずです。

于 2011-09-22T12:51:33.913 に答える
2

:Derickの答えは正しいと思いTypeError: Cannot call method 'isFirstTrack' of undefinedます—メッセージを説明しています—しかし、この答えも適切かもしれません。)

あなたは言う

方程式からjQueryを削除すると、正常に機能します。

つまり、線を切り取った場合jQuery ->、テストは合格ですか?その場合、それはスコープの問題ではありません。これはコードの順序の問題です。関数をjQueryに渡すと、ドキュメントの準備ができるまでその関数は実行されません。Albumその間、テストは、AlbumViewクラスが定義される直前に実行されます。

jQuery ->クラス定義は既存のDOM要素に依存しないため、ラッパーを使用する理由はありません。

于 2011-09-22T15:20:29.953 に答える