In javascript, assigning a non-primitive value (Such as Object, Array, Function, and many more), keeps a reference (an address in the memory) to the assigned value.
Assigning a primitive value (String, Number, Boolean, or Symbol) to two different variables, and changing one, won't change both:
var x = 5;
var y = x;
y = 6;
console.log(y === x, x, y); //false, 5, 6
But with a non-primitive value, since both variables are simply keeping references to the same object, changing one variable will change the other:
var x = { name : 'John Doe' };
var y = x;
y.name = 'Jhon';
console.log(x.name === y.name, x.name, y.name); //true, John, John
In angular, when a scope is created, it is assigned all of its parent's properties However, changing properties afterwards will only affect the parent scope if it is a non-primitive value:
angular.module('app', [])
.controller('myController', ['$scope', function($scope){
$scope.person = { name: 'John Doe' }; //non-primitive
$scope.name = 'Jhon Doe'; //primitive
}])
.controller('myController1', ['$scope', function($scope){}]);
<div ng-app="app" ng-controller="myController">
binding to input works: {{person.name}}<br/>
binding to input does not work: {{name}}<br/>
<div ng-controller="myController1">
<input ng-model="person.name" />
<input ng-model="name" />
</div>
</div>
Remember: in Angular scopes can be created in many ways (such as built-in or custom directives, or the $scope.$new()
function), and keeping track of the scope tree is probably impossible.
Using only non-primitive values as scope properties will keep you on the safe side (unless you need a property to not inherit, or other cases where you are aware of scope inheritance).