AngularJS and a JS prototypal inheritance gotcha

Like many of you I’ve been shoring up my bits on AngularJS from Google. Really slick stuff that in short, extends HTML with attributes, something possible since well before HTML5: HTML5 Data Attributes. While watching a series of videos on Angular at http://egghead.io/ I came upon the title of ‘The Dot’ that addresses a rather popular seemingly buggy behavior. I cranked up a JSBin page for you to see the behavior and experiment http://jsbin.com/oviwan/2/edit

In short this is based on JavaScripts prototypal inheritance. Seems the above is very often considered a bug in AngularJS. You can get a full and deep description of things here The-Nuances-of-Scope-Prototypal-Inheritance

This whole topic got me to thinking about scope in AngularJS, not $scope, but scope. When you create a Angular fragment like the below, just what does scope mean and what is in scope? Because $scope is a bit of a important literal in AngularJS, this is rather hard to go and google.

Upon first gander, nothing unusual here, eh? The first ‘one’ section does some simple binding, the rest though all use the same model in name, data.message. These are all introduced on the same ‘level’ so to speak, but what’s the scope tree look like? Well, what do you think the behavior is of this small fragment? Check it out here http://jsbin.com/ibaded/1/edit

The first ‘one’ section is no surprise. Entering data in ‘two’, ‘three’, and ‘four’ is not surprising either. But wait! There’s more! Refresh and change the order, that is enter data in sections ‘four’, ‘three’, then ‘two’, see the difference? This is the prototype inheritance in action, but why? Scope! So, what how and where in Angular? Enter Batarang. Batarang is a nifty Chrome plugin for introspecting your Angular application. It is installed as a new tab on the developer tools window. So, grab the code at the JSBin link above and put it on your local host there, load it, and open up the dev tools, then nav to the AngularJS tab. You should see this sort of layout

batarang_one

This Batarang window is interactive, click ‘models’ to drill down and such. Click on ‘scope’ to be taken direct to the Elements tab in dev tools and have the element surrounding that scope be highlighted! Now, fill in the inputs top down and you should see this sort of information

Batarang_two

Now refresh and fill in the inputs backwards, bottom up. You should see the Batarang model displayed quite differently.

batarang_three

Why is this? It is due to the way JS works the prototype chain. Assignments of variables are immediate and happend within the current class. Reads however consult the current class, then recursively consult the prototype chain, in other words the parent classes until it is found. Thus a line like

var x = 5

will immediately assign 5 to x in the current scope. A line like

var foo = x

will incur a lookup through the chain, starting with the current scope. Couple this together like so

var data.message = “I am one”

and we see both a read and write in that order. The read of course consults the chain FIRST! if it finds data it uses it to create and assign message, where ever in the chain it was found. If JS does NOT find data, it then creates it where it stopped looking in the chain. Thus the behavior seen in the example!

There you have it. Though we are working using a descriptive tool such as Angular, its all JS still and we have to live by its rules. Using a tool like Batarang is immensely helpful in understanding the magic AngularJs provides.

For a Deep Read on protypical inheritance, check out this paper http://web.media.mit.edu/~lieber/Lieberary/OOP/Delegation/Delegation.html

This entry was posted in CSS3, HTML5, JavaScript, Techy, Universal Mind. Bookmark the permalink.