The previous example is good enough when we need to bind a single html element, to a single variable.
In reality - we need to bind many elements to many variables:
<span ng-repeat="number in [1,2,3,4,5]">{{number}}</span>
This ng-repeat
binds 5 elements to 5 variables called number
, with a different value for each of them!
The way angular achieves this behavior is using a separate context for each element which needs separate variables. This context is called a scope.
Each scope contains properties, which are the variables bound to the DOM, and the $digest
and $watch
functions are implemented as methods of the scope.
The DOM is a tree, and variables need to be used in different levels of the tree:
<div>
<input ng-model="person.name" />
<span ng-repeat="number in [1,2,3,4,5]">{{number}} {{person.name}}</span>
</div>
But as we saw, the context(or scope) of variables inside ng-repeat
is different to the context above it.
To solve this - angular implements scopes as a tree.
Each scope has an array of children, and calling its $digest
method will run all of its children's $digest
method.
This way - after changing the input - $digest
is called for the div's scope, which then runs the $digest
for its 5 children - which will update its content.
A simple implementation for a scope, could look like this:
function $scope(){
this.$children = [];
this.$watches = [];
}
$scope.prototype.$digest = function(){
this.$watches.forEach(function($w){
var val = $w.val();
if($w.prevVal !== val){
$w.callback(val, $w.prevVal);
$w.prevVal = val;
}
});
this.$children.forEach(function(c){
c.$digest();
});
}
$scope.prototype.$watch = function(val, callback){
this.$watches.push({val:val, callback:callback, prevVal: val() })
}
note: this is example is a demonstration, not the actual angular code