3

次の 2 つの CoffeeScript クラス定義があります。私はそれらが同じ動作をすることを期待していましたが、そうではありません。A特にのインスタンスへのアクセスDoesNotWorkは未定義です。

fields = ["A","B","C"]

class DoesNotWork
  constructor: () ->
    _.each(fields, (f) -> @[f] = ko.observable(''))

class DoesWork
  constructor: () ->
    @A = ko.observable('')
    @B = ko.observable('')
    @C = ko.observable('')

上記のコードは次のようにコンパイルされます

var DoesNotWork, DoesWork, fields;
fields = ["A", "B", "C"];
DoesNotWork = (function() {
  function DoesNotWork() {
    _.each(fields, function(f) {
      return this[f] = ko.observable('');
    });
  }
  return DoesNotWork;
})();
DoesWork = (function() {
  function DoesWork() {
    this.A = ko.observable('');
    this.B = ko.observable('');
    this.C = ko.observable('');
  }
  return DoesWork;
})();

私が微妙に見逃している初心者のJSは何ですか?

4

3 に答える 3

6

さらに別の解決策 (おそらく最も読みやすく効率的) は、スキップ_.eachして代わりに CoffeeScript のfor...in繰り返しを使用することです。

for f in fields
  @[f] = ko.observable ''

ループを後置してワンライナーにすることもできます。

@[f] = ko.observable('') for f in fields

CoffeeScript のループは、コンテキストを作成したり、スコープに影響を与えたりしないことに注意してください。関数のみが行います。

于 2011-03-29T20:32:29.027 に答える
4

_.each に渡される匿名関数の 'this' は、親オブジェクトではなく、匿名関数にバインドされます。_.each ではコンテキスト オブジェクトを渡すことができるため、これは適切にバインドされますが、

http://documentcloud.github.com/underscore/#each

したがって、それぞれの 3 番目の引数でバインドしようとしているオブジェクトに参照を渡します。

class ShouldWorkNow
  constructor: () ->
    _.each(fields, ((f) -> @[f] = ko.observable('')),this)
于 2011-03-29T17:57:26.637 に答える
3

Craigの答えは正しいですが、別の解決策は無名関数をバインドされた関数として定義することです。この場合、それはあなたが書くことを可能にするでしょう

_.each(fields, ((f) => @[f] = ko.observable('')))

バインドは=>、関数が定義されているコンテキストに関数をバインドするため、this関数がどのように呼び出されても、関数内で常に同じことを意味します。これはコールバックにとって非常に便利な手法ですが、の場合、_.each渡すよりも少し効率が悪くなりthisます。

アンダースコアを使用して同じことを行うには、次のように記述します。

callback = _.bind ((f) -> @[f] = ko.observable('')), this
_.each(fields, callback)

しかし=>、タイピングの多くを節約できます!

于 2011-03-29T20:28:04.537 に答える