web-dev-qa-db-ja.com

jQuery .each()内のCoffeescript 'this'

次のようなコーヒースクリプトがあります:

class foo:
    @bar = 'bob loblaw'

    processRows: ->
        $("#my-table>tr").each ->
            id = $(this).attr("id")
            @processRow id

    processRow: (id) ->
        console.log @bar + id

私の問題は:thisを取得するためにループ内の.eachコンテキストを参照するにはidが必要ですが、foo.processRow()内のクラスインスタンスを参照するにはthisも必要です---それは現在していません。

_this = this関数の外側で.eachのようなものを使用して渡すことは、processRow内の多くのクラス変数を参照するため、優れたソリューションではありません。

何かご意見は?明らかな何かが欠けていますか?ありがとう!

54
user524276

jQuery.each は、現在の要素をコールバックの2番目のパラメーターとして渡すため、jQuery用にthisを予約するhaveをしないでください。

processRows: ->
    $("#my-table>tr").each (index, element) =>
        id = $(element).attr("id")
        @processRow id

fat arrow=>)構文コールバック関数。関数のコンテキストをthisの現在の値にバインドします。 (コールバック関数のthisは、関数を定義したときのthisと常に同じです。)

128
Arnaud Le Blanc

あなたは言う

ProcessRow内で多くのクラス変数を参照するため、_this = this関数の外で.eachのようなものを使用して渡すことも、優れたソリューションではありません。

ただし、これは最も効率的なソリューションです。 JavaScriptのthisは奇妙な獣です。 =>演算子を使用してネストされた関数内に固定しておくことができます。これは、回答でarnaud576875が推測するため(エレガントですが非効率的)、またはthisを別の変数しかし、エレガントではありません)。選択はあなた次第です。

一部の最新のブラウザは、すべての関数でbindメソッドをサポートしていることに注意してください。これはCoffeeScriptの=>よりも効率的です。 =>がネイティブbindを使用できるようにするためのオープンチケットがあります。 https://github.com/jashkenas/coffee-script/pull/1408

補遺:もちろん、上記のどれよりも効率的な代替案は、

for element, index in $('#my-table>tr')
  ...

this問題も解決します。

6
Trevor Burnham

あなたのコード...

class foo
    @bar = 'bob loblaw'

    processRows: ->
        $("#my-table>tr").each ->
            id = $(this).attr("id")
            @processRow id

    processRow: (id) ->
        console.log @bar + id

に変換されます...

var foo;
foo = (function() {
  function foo() {}
  foo.bar = 'bob loblaw';
  foo.prototype.processRows = function() {
    return $("#my-table>tr").each(function() {
      var id;
      id = $(this).attr("id");
      return this.processRow(id);
    });
  };
  foo.prototype.processRow = function(id) {
    return console.log(this.bar + id);
  };
  return foo;
})();

これは、翻訳先の現在のコンテキストについて多くを想定しています。残念ながら、jQueryはコンテキストを管理するため、明示的であるか、クラスのthisへの参照を宣言する必要があります。

ちなみに、生成されたコードには他にも問題があります。この縮小されたケースを見てください。

class foo
    @bar = 'bob loblaw'

    getBar: () ->
        @bar

トランスパイル:

var foo;
foo = (function() {
  function foo() {}
  foo.bar = 'bob loblaw';
  foo.prototype.getBar = function() {
    return this.bar;
  };
  return foo;
})();

このコードを使用しようとした結果:

> foo.bar;
"bob loblaw"

> var f = new foo();
undefined

> f.getBar();
undefined

あなたのコードは@barは独自のプロパティですが、foo関数の静的プロパティとして作成されています

4
Rick