Javascript – Undefined array values vs Undefined array indices

Javascript arrays, like any non-primitive, are technically considered objects. This means various object methods and operators are available to them, but internally they’re a different beast. And this can cause unexpected results when treating them like an object.

This is a simple test you can run in your developer console for your browser.

a = [1, 2, 3]
delete a[2]

If javascript arrays act in a similar fashion to a javascript object, you would expect the array to have shrunk by one element.

It doesn’t.

a.length
-> 3

Well, this is strange, and it gets stranger when you print out the array:

a
-> [1, 2, undefined x 1]

Undefined x 1… What does that mean? Every time you delete an array element, it creates an undefined index.

Now, the mystery thickens when you try and play with undefined values.

a.push(undefined)
-> [1, 2, undefined x 1, undefined]

Wait! Why is there undefined x 1, and a separate, different undefined? How are they different? According to the javascript type system, they are the same:

typeof a[2]
-> "undefined"
typeof a[3]
-> "undefined"
typeof a[2] === typeof a[3]
-> true
a[2] === a[3]
-> true
a[2] == a[3]
-> true

A cursory look suggests they’re entirely equivalent, just represented differently. Unfortunately not.

for (property in a) {
    console.log(property + ' ' + a);
}
-> 0 1
-> 1 2
-> 3 undefined

The index itself can be undefined, or the value can be undefined. In our example, a[2] is an undefined index. The index does not exist. Whereas a[3], the index exists, but its value is undefined. This is made apparent when we enumerated over the indices of our array. Ironically, both of them contribute to the overall length of the array, but only one of them holds a value.

If you’re still having trouble conceptualizing this, think of it as such:

a
-> 0 = 1
-> 1 = 2
-> 2 = ???
-> 3 = undefined

a[2] just doesn’t exist. a[3] does, and it is undefined. Careful, the type of a[2] and a[3] are both undefined, which makes some strange literal sort of sense. Now, I could lecture on the importance of understanding the javascript type system until you, my faithful pupils, flee from my blog. But instead, I’ll leave you with this, the simply way of deleting array elements:

a.length = 2
a
-> [1, 2]

The “No jQuery Challenge”

This post is about Angular.js

I discovered Angular no more than two months ago. The simplicity of it convinced me to start the project that had been brewing in my mind a couple years. When I first stumbled upon Angular, I thought to myself, “Wow, I can make complex web applications really quickly if I combine this with jQuery”.

But funny enough, I discovered as I wrote my application that not only did I not need to use jQuery, I did not even want to. Angular provides an alternative way of thinking about the problems jQuery solves.

It became a point of pride to eschew jQuery. I do have my reasons, however, and I’ll share why the No jQuery Challenge is a great learning tool.

Say you find a jsFiddle example with some HTML:

<div id="container">
  <div id="form">
    <input id="submit" type="submit" value='click'></input>
  </div>
  <!-- more html here --> 
</div>

The resulting webpage looks fairly sparse.

Screen shot 2013-12-18 at 1.32.32 AM

There seems to be something misplaced, but we’re in a hurry so we do what we’re told not to and click the button. When we do, we are greeted by a popup box.

Screen shot 2013-12-17 at 7.29.02 PM

A quick glance at the HTML reveals no understanding as to why the popup box appears, so you check the javascript file.

You’re thinking this is jQuery magic. I’ll just ctrl+f for a $(‘#submit’) and find the javascript that generates the dialog box. Doing so finds us:

$('#submit').attr('value', 'don\'t click');

This explains one mystery, but not the one we’re interested in. Now, the javascript file could be fairly large, so the code we’re looking for might be buried deeper. When ctrl+g finds no other instances of $(‘#submit’), we look back at the HTML to see what other jQuery selectors might be in play.

Maybe the <div id=”form”> is responsible. When we search for the $(‘#form”), we find nothing. Surely, it can’t be the <div id=”container”> responsible for this? So we check, and find this:

$("#container").children().addClass('clickable')

Okay, a class titled ‘clickable’, which seems to be what we’re looking for. When we search for a selector of ‘clickable’, we find what we’ve long been searching for:

$(".clickable > input").bind("click", function () {
  alert("popup");
});

Our quest comes to an end; all inputs whose parents are of ‘clickable’ class gives us a dialog box.

While this example is somewhat farfetched and unnecessarily complex, these sorts of design patterns are pretty much everywhere in large dynamic web apps. The more jQuery is used to manipulate the DOM and alter the project structure, it becomes exponentially more difficult to follow the train of logic.

With that in mind, lets take a look at an Angular implementation of the same functionality:

<div>
  <div ng-click="popup()">
    <input value="{{inputText}}"></input>
  </div>
</div>

Here, it becomes immediately clear the intended behavior. The <input> tag’s value is wrapped in double curlybraces, thus bound to a variable and subject to change. The inner <div> does *something* when clicked. If we want to know what, we are certain it’s hidden in a function called popup.

Taking a look at the controller:

$scope.inputText = "don't click";
$scope.popup = function () {
  alert("popup");
}

The behavior being explicitly stated within the HTML is called the ‘Declarative Approach’ of Angular. It means that the HTML specifies pretty much all of the behaviors that interact with it, making it easy to understand what happens to each tag. As you use Angular, you’ll find it becomes impossible to obfuscate the logic as I did in the jQuery example above.

As I developed in Angular, I felt the urge to utilize jQuery within my project, but as I learned the ‘Angular Way’, I discovered that less and less I even needed to.

After a short while, I found there’s rarely ever a need to utilize ‘id’ attributes or use classes for use beyond styling.

Ultimately, I failed the No jQuery Challenge (I used the jQuery cookie parser). I don’t actually advocate avoiding jQuery for an angular application, as they’re entirely compatible libraries and jQuery has multitudes of advantages. However, I did find it to be a useful mindset to adopt where, every time I considered using a jQuery selector I asked myself, “Can I do this without jQuery?” I end up discovering that Angular provides for so many great and extensible ways of solving our problems.