日本語のアノテーションがついているソースコードを読んだので、ちょっとわかりにくかったあたりをメモっておく。
コールバックリスト(107行目)
リスト構造にしてあんのかなと思ったがtailってなんだろうと思ったら最後尾を常に指すようにしているらしい。
while (event = events.shift()) {
list = calls[event];
node = list ? list.tail : {};
node.next = tail = {};
node.context = context;
node.callback = callback;
calls[event] = {tail: tail, next: list ? list.next : node};
}
これは最後尾のobjectのnextとtailが同じ物を指すようにしているのでさくっと最後に空のオブジェクトの参照を保持している。全てのコールバックを実行するのはnextでたどればいいようになっている。Spine.jsは普通に配列使っていたけどリストにするメリットはなんかあるのかなぁ。
実際の動きはこんな感じ。
> node = {}
{}
> node.next = tail = {}
{}
> node.context = "ctx1"
'ctx1'
> node.callback = "callback1"
'callback1'
> calls = {tail: tail, next: node}
{ tail: {},
next:
{ next: {},
context: 'ctx1',
callback: 'callback1' } }
> list = calls
{ tail: {},
next:
{ next: {},
context: 'ctx1',
callback: 'callback1' } }
> node = list.tail
{}
> node.next = tail = {}
{}
> node.context = "ctx2"
'ctx2'
> node.callback = "callback2"
'callback2'
> calls = {tail: tail, next: list.next}
{ tail: {},
next:
{ next:
{ next: {},
context: 'ctx2',
callback: 'callback2' },
context: 'ctx1',
callback: 'callback1' } }
tailとnextは同じ空のオブジェクトを指しているので、常に次の参照を保持したまま大きくなっていく。
void 0 (283行目)
void 0はundefinedになる。
success = option.success (342行目)
if (success) success(model, resp);って何やっているのかなぁと思ったのだが、opttion.successを上書きしてしまうので、元々のoption.successを残しておいてコールバックで呼び出しているだけだった。
var model = this;
var success = options.success;
options.success = function(resp, status, xhr) {
if (!model.set(model.parse(resp, xhr), options)) return false;
if (success) success(model, resp);
};
options.error = Backbone.wrapError(options.error, model, options);
return (this.sync || Backbone.sync).call(this, 'read', this, options);
},
element (1190行目)
$elとelが存在する。
this.$el = (element instanceof $) ? element : $(element);
this.el = this.$el[0];
ステートフルJavascriptを読んであればそんなに難しくないので、コードリーディングにちょうどいいかも