howdylikes

Google Developersってわかりづらいよね

AngularJS 変更監視 Scope#$watchの補足とScope#$apply

$watchについて以前書きましたがその補足と$applyについてです。
blog.howdylikes.jp

文字列の代わりにfunctionで変更監視対象を直接指定することが可能

と記載しましたがその補足です。
以下のscript内ではwindowオブジェクトのglobalを監視対象としています(普通は書きませんが動作確認のためです)

this.dummy()が呼ばれた場合もScopeの監視処理自体は走ります。
※ng-clickで$digestサイクルが実行されるかららしい

changeValue()が呼ばれた場合、globalを書き換えても$digestサイクルが実行されないのでScopeの監視処理は走りません。

callApply()内で$scopeを取得して$apply()を実行していますが、これは内部的に$digestサイクルを実行しているということらしい。

つまりchangeValue()の後にthis.dummy()callApply()など$digestサイクルが実行されるような処理を行えばthis.clickと同じような動きになる。

var global = 'hello, world';

angular.module('myapp', [])
    .controller('myController', function ($rootScope, $scope) {
        $rootScope.$watch(
            function () {
                console.log('監視処理が動く');
                return global
            }, function (newValue, oldValue, scope) {
                console.log('globalが変更されました:' + newValue) ;
            });

        this.click = function() {
            console.log('this.click');
            global = new Date();
        }
        this.dummy = function() {
            console.log('this.dummy');
        }
    });

function changeValue() {
    console.log('changeValue');
    global  = new Date();
}

function callApply() {
    console.log('callApply');
    angular.element('#myCtrl').scope().$apply();
}

まとめ

$watchは監視処理を定義する
$digestサイクル内で監視処理を呼ぶ($rootScopeから先に呼ばれていたことから察すると$rootScope(親Scope)が優先順位が高いと思われる)
ng-clickなど$digestサイクルを呼ぶ処理がある(入力値を変えた時とかもおそらく呼ばれている=これがAngularのデータバインディングの正体か)