Understanding prototypal inheritance in Angular’s $scope

Willson Mock
4 min readApr 22, 2014

Angular.js

Like many folk’s before me, I’ve been learning Angular.js by watching videos from egghead.io (these are some of the best angular videos out there). One particular video caught my attention though — it’s titled “The Dot.” I’ll reproduce the code below for your convenience:

<!doctype html>
<html ng-app='MyApp'>
<head>
<meta charset='utf-8'>
<title>Egghead</title>
<script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js'></script>
<script>
angular
.module('MyApp', [])
.controller('FirstCtrl', ['$scope', function ($scope) { // empty here for now
}])
.controller('SecondCtrl', ['$scope', function ($scope) {
// empty here for now
}]);
</script>
</head>
<body>
<!—- part of $rootScope -->
<input type='text' ng-model='data.message'><br>
<p>{{ data.message }}</p>
<div ng-controller='FirstCtrl'>
<!-- part of FirstCtrl's $scope -->
<input type='text' ng-model='data.message'>
<p>{{ data.message }}</p>
</div>
<div ng-controller='SecondCtrl'>
<!-- part of SecondCtrl's $scope -->
<input type='text' ng-model='data.message'>
<p>{{ data.message }}</p>
</div>
</body>
</html>

If you copy and paste this into your editor of choice, load it into your browser, and play around with the input boxes, you’ll immediately see why I found this example interesting:

Depending on the order in which you interact with the input boxes, you’ll see Angular’s data-binding produce different behaviors!

Go ahead and try this out to confirm:

Scenario 1

  1. Type into the 1st input box. You’ll see that all three input boxes show the same text.
  2. If you subsequently type into the 2nd or 3rd input box, you’ll see that again all three input boxes display the same text.

Scenario 2

  1. Refresh your browser page first (this should bring you back to where all the input boxes are empty).
  2. Now, instead of initially typing into the 1st input box, type into the 2nd input box first. You’ll see that only the 2nd input box’s text changes.
  3. If you type into the 3rd input box next, then you’ll see that only the 3rd input box’s text changes.
  4. And finally, if you type into the 1st input box, then you’ll see that only the 1st input box’s text changes.

These 2 scenarios demonstrate that the order in which you type into the input boxes will produce different behaviors. Now, I know what all of you are thinking — but no, don’t throw your computer against the wall in confusion! There’s actually a logical explanation for why this is happening!

JavaScript Prototypal Inheritance

As my heading suggests, it all has to do with JavaScript’s Prototypal Inheritance. For those of you who aren’t familiar with prototypal inheritance and want to understand it more in the context of Angular $scopes, here’s an awesome article to read:

https://github.com/angular/angular.js/wiki/Understanding-Scopes

Going back to our problem, in order to understand why different behaviors are happening for these two scenarios, you have to realize that the $scope object in Angular is just a plain old JavaScript object (“pojo”). What this means is that the $scope object follows the same rules of prototypal inheritance like any other object in JavaScript. Another key point to realize is that each controller will have its own $scope object, and as a catchall, there’s one $rootScope object (although it’s not advisable to use the $rootScope object because it’s similar to polluting the global namespace).

Given that we know how prototypal inheritance works in JavaScript, let’s break down each scenario and examine it further.

Explanation of 1st Scenario

By typing into the 1st input box before typing into any other one, what’s happening behind the scenes is that Angular checks whether there is a ‘data’ property associated with the $rootScope object (since the 1st controller’s scope object is $rootScope). Since there isn’t, Angular will automatically create a ‘data’ property that references a new object and adds a ‘message’ property onto that new object (along with the data-bound value for the ‘message’ property). If you then type into any of the 3 input boxes, all three input boxes will share the same values.

So why does this happen?

It might seem weird that this behavior is happening, but if you think back to how prototypal inheritance works, it makes perfect sense. Even though there are 3 distinct $scope objects, each $scope object’s data property actually refers to the same object (the one in $rootScope). Typing into the 1st input box is no different from typing into any of the other 2 input boxes. Think about it — if you type into the second or third input box, Angular will try looking up the ‘data’ property on the corresponding controller’s $scope object. Since there isn’t one in either FirstCtrl or SecondCtrl, Angular will then look up the ‘data’ property in the $rootScope object (prototypal inheritance to the rescue)!

So what happens with the 2nd scenarios?

Explanation of 2nd Scenario

This time, though, we decided to type into the 2nd input box first. Because the ‘data’ property doesn’t exist on either the FirstCtrl’s $scope object or the $rootScope object, Angular will automatically assign a new ‘data’ object to the current $scope object — which is the FirstCtrl’s $scope object. The same can be said about typing into the 3rd input box next — Angular will again create a new ‘data’ object on the current $scope object (Second Ctrl’s $scope object). I’m sure you can see that the same logic will apply when typing into the first input box — the $rootScope object will create its own new object associated with the ‘data’ property. In the end, each $scope object will have its own ‘data’ property and not share a reference to the same object associated with the ‘data’ property.

Conclusion

So really, this post’s goal is two-fold:

  1. To show that JavaScript actually makes sense (although sometimes it can be tricky to follow)
  2. To clarify a common point of confusion that trips up many Angular developers

Feel free to add any comments!

My name is Willson Mock and I’m a co-founder at Altitude Labs. We’re a web and mobile development consultancy based in Hong Kong. We connect with startups and corporate clients to build amazing products.

--

--

Willson Mock

I’m an avid learner, and I write about web technologies, personal fitness, and other fun stuff. http://willsonmock.com