We need to pay special attention when we're working with nested controllers. Defining variables directly on the $scope objects managed by the controllers can have unexpected behaviors if we don't know how AngularJS works.
Here we have firstControllerScope, secondControllerScope and thirdControllerScope. All of them define variables directly on their respective $scope objects.
firstControllerScope defines the firstName variable and binds it to an input element in the HTML template. Whenever the user types something in the input element, the firstName value changes accordingly.
secondControllerScope is nested inside firstControllerScope. secondControllerScope defines a new lastName variable on its own $scope object and the getFullName function that uses both a firstName and a lastName variable to return a result. In the HTML template, both firstName and lastName are bound to some elements inside the DOM tree rooted in the div where secondControllerScope is defined. When the page is first loaded, the value of firstName in the DOM tree belonging to secondControllerScope is taken from the scope of the first ancestor controller that has the variable defined in its $scope, in this case from firstControllerScope, because that variable is not defined by secondControllerScope. When the user types in the input element inside the firstControllerScope DOM tree, the value changes also in the elements bound to the firstName variable in the children controllers, but as soon as the user types something in the input element belonging to the DOM tree of secondControllerScope and bound to firstName, then a new variable named firstName is created in the $scope object managed by secondControllerScope. From that moment, there are two different instances of firstName belonging to the scopes of firstControllerScope and secondControllerScope and whenever the user types on the input of firstControllerScope, only its own copy of the variable changes.
The same behavior can be observed also in thirdControllerScope, but here we show that we can access the value of the lastName variable in the parent scope simply using the $parent notation.
There's a solution to avoid possible conflicts and we see it in firstControllerObj, secondControllerObj and thirdControllerObj. Essentially, we just define the variables inside distinct objects and define the objects on the scopes of the three controllers. In this way there's no overriding of the variables whenever the user types in any of the input elements and we can avoid unexpected behaviors.