1

最近、自分のコードで興味深いバグに遭遇しました。どうにかして修正を見つけることができましたが、解決策が機能する理由を誰かが説明できるかどうか疑問に思っています。ここにいくつかのコードがあります

var Project = Backbone.Model.extend({
  initialize: function() {
    // Uncomment this line and you will no longer get the alert
    //_.bindAll(this);
  },
}, {
  parse: function() {
    alert('Parsing data');
  }
});

var project = new Project({});
project.constructor.parse();

parsebindAll をこのように使用すると、すべての関数が現在のスコープにバインドされることは理解していますが、クラス プロパティ関数に影響する理由はわかりません。インスタンスのプロパティにのみ影響すると思います。

4

1 に答える 1

1

_.bindAll1.4.4は、メソッド名を指定せずに (正常に) 呼び出すことができるUnderscore の最後のバージョンであるため、1.4.4 を見ていきます。

_.bindAll実装は非常にシンプルで、レビューすると問題が解決するはずです。

_.bindAll = function(obj) {
  var funcs = slice.call(arguments, 1);
  if (funcs.length === 0) funcs = _.functions(obj);
  each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
  return obj;
};

3 行目が重要です。

funcs = _.functions(obj);

したがって、バインドする関数を指定しない場合、Underscore は関数であるすべてのオブジェクトのプロパティを取得し、それらすべてをバインドします。詳細については、_.functions実装ドキュメントを確認してください。

しかし、constructorプロパティは何ですか?さて、それは

... インスタンスのプロトタイプを作成した Object 関数への参照

これは_.isFunctionテストに合格し、上記の配列にconstructorなります。funcsつまり、次constructorの 4 行目のラッパー関数に置き換えられます_.bindAll

obj[f] = _.bind(obj[f], obj);

しかし、そのラッパー関数には、元の関数が持つプロパティ ( などparse)がまったくなくproject.constructor、すべてが混乱とナンセンスの山にバラバラになります。

この種の混乱は、おそらく 1.5+_.bindAllが言う理由です:

bindAll _.bindAll(object, *methodNames)

[...] methodNamesは必須です。

オブジェクトのプロパティを反復処理して、どれが関数でどれがそうでないかを判断しようとすると、他の奇妙な問題に遭遇することもあります。


予期せぬ事態が発生した場合は、Underscore と Backbone のソースを参照することをお勧めします。どちらも非常に読みやすく、理解しやすいものです。

于 2013-08-09T04:23:01.103 に答える