AngularJsのrootScope.jsに関するメモ
Scope::$new(isolate)
isolateなscopeは共有するために\(asyncQueue、\)postDigestQueueを代入している。
子scopeはthis.\(childScopeClass.prototype = thisすることで親scopeを代入して共有している。
親scopeと子scopeのデータ共有がthis.\)childScopeClass.prototype = thisで行われている。
共有されないものが$$childScopeClassの属性になっている。
Scope::$watch(watchExp, listener, objectEquality)
$parseは関数を引数に渡されたときはそのまま関数を返す。
compileToFnはwatchExpを$parseする。
noopはfunction noop() {}で何もしない関数
scope.$$watchers = []に以下のオブジェクトを格納する。
unwatchするための関数を返す。
Scope::$watchGroup(watchExpressions, listener)
複数のwatchExpを1つのlistenerに紐付ける。
各watchExpを$watchする。そのcallbackがchangeCount++する。
changeCountを返すwatchExpのcallbackにlistenerを指定する。
unwatchCountが0になるとlistener.$$unwatchがtrueになる。
Scope::$watchCollection(obj, listener)
指定されたscopeの属性の型がarrayやobjectだったときそれらの属性の変化を監視する。
指定されたscopeの属性の型がarrayの場合は配列の要素を監視する。
指定されたscopeの属性の型がobjectの場合は属性を監視する。
以下の文で処理を行っている。
return this.$watch($watchCollectionWatch, $watchCollectionAction);
$watchCollectionWatch()
oldValueにすべての型の古い値が格納される
innerArrayにarray型の古い値が格納される
innerObjectにobject型の古い値が格納される
newValueがobjectかarrayでoldValueがinnerArrayやinnerObjectと同じオブジェクトを参照していない場合、
空のarrayもしくはobjectをoldValueやinnerArray、innerObjectに代入する。
oldValueとinnerArrayやinnerObjectが同じオブジェクトを参照するようにする。
$watchCollectionAction()
listenerを実行する
veryOldValueにnewValueをコピーして次に実行した際にlistenerにそれを渡す。
Scope::$digest()
スコープと子スコープのwatchを実行する。
listenerをが実行されなくなるまで繰り返し実行される。
手動で実行したいときはScope::$applyを利用する。
\(asyncQueue,\)postDigestQueueは親scopeと共有する。
watcher.getはcompileToFn(watchExp, ‘watch’)
watcher.getの引数にscopeを渡している
watch = watchers[length];
watch.get(current)とwatch.lastを比較して異なっていればwatch.lastにwatch.get(current)を代入する。監視対象が変化してlistenerを実行する。
lastDirtyWatchには最後に実行されたlistenerのwatchが格納される。
listenerを実行するオブジェクトの走査は$digestを呼びだしたscope以下のスコープすべてを対象にして行われる。
targetは$digestの呼び出しもとのscopeが入る。$digest中は変化しない。
currentは走査中に検査対象になったscopeが入る。
lastDirtyWatch === watchもしくはscopeの親子間の走査でttlが1減る。
lastDirtyWatch === watchのときdirtyはfalseになる。
監視対象が変化してlistenerを実行する時dirtyはfalseになる。
watchしているscopeの走査が終了条件 while (dirty || asyncQueue.length);
$digestを呼びだしたscope以下の走査は以下の部分で行っている
Scope::$destroy()
該当scopeを親scopeから削除する。
$destroyを該当scopeからbroadcastする。
該当scopeの他のscopeへの参照を削除する。
Scope::$eval(expr, locals)
scopeの属性を引数に応じて処理する。
文字列と関数のどちらかを第1引数にする。
第2引数にはscopeをoverrideする値を指定する。
Scope::$evalAsync(expr)
$browser.defer(fn)はfnをsetTimeoutで実行する
this.$$asyncQueue.push({scope: this, expression: expr});
Scope::$$postDigest(fn)
this.$$postDigestQueue.push(fn);
Scope::$apply(expr)
angular内で実行したい処理を引数に取る。
$eval(exp) => $digest()
Scope::$on(name, listener)
$emitや$broadcastで呼ばれるlistenerを登録する。
\(listenersにnameをkeyにして配列にlistenerを格納する。
親スコープをたどって先祖スコープすべてに\)listenerCount[name]++する。
Scope::$emit(name, args)
argsはlistenerに引数で渡される。
listenerに渡されるeventは以下の内容
Scope::$broadcast(name, args)
argsはlistenerに引数で渡される。
listenerに渡されるeventは以下の内容
var $rootScope = new Scope();
decrementListenerCount(current, count, name)
$onの戻り値
親スコープをたどって、親スコープのcurrent.\(listenerCount[name]をcount分減らす。 current.\)listenerCount[name] === 0だったらdelete current.$$listenerCount[name];する。