A commenter – Josh - pointed out a small error in some code I posted a while back regarding a CSS property watcher component that can monitor changes in any CSS property and notify you by firing a function. The jQuery plug-in code keeps track of CSS properties and values in an array and whenever the properties monitored change an event is fired to let the event consumer know of the change and take appropriate action based on the change.
My error in the code relates to how the array was declared which was:
var data = {
props: props.split(","),
func: func,
vals: [props.split(",").length],
itvlId: itId
};
The intent was to create an empty array of the specified length, but that’s of course not what happens. It’ll create an array of 1 element with the length as a value. The real intent would have been correctly expressed as:
vals: new Array(props.split(",").length)
As it turns out though the old code that used the array still worked, because JavaScript dynamically creates array elements as you assign them without having to first initialize the whole array up front and so the following code still works just fine even with the original, incorrect array declaration:
$.each(data.props, function(i) { data.vals[i] = el.css(data.props[i]); });
This code loops through the properties array and creates the array on the fly simply by setting the indexer of the vals array which is created dynamically.
Specifcally Javascript arrays auto-size just like this:
var ar = []
ar[2] = 1;
debugger;
results in a 3 element array that looks like this (in FireBug):
The array length is 3 and the array behaves just like a pre-sized array. Any non-referenced elements will be created as undefined.
It’s nice that Javascript will automatically re-dimension an array for you, but it’s probably still a good idea to pre-size to avoid the constant resizing that is required internally. Assigning existing elements surely is more efficient than having to check and resize the array on each hit.
This behavior also can make it easy to accidentally create an out of bounds array (for your intended usage anyway) and bugs along those lines would be pretty hard to track down. So some care is required along those lines.
Here’s another interesting little factoid around dynamic array elements. Check out this snippet of code:
var ar = []
ar["test"] = 4;
ar[3] = 1;
var len = ar.length;
debugger;
and take a guess – what is the size of the array after this bit of code runs?
The code creates an array that has mixed numeric and string indexers. And yes this actually works – you can reference both ar[3] and ar[“test”] and get the expected results. Here’s what the resulting array looks like in FireBug:
Note that array’s length is 4 – even though there are 4 numeric elements and the one text ‘element’. In other words the string indexers don’t affect the length of the array. Instead the ‘string’ indexer effectively becomes an expando property on the array object. The Visual Studio Javascript debugger actually demonstrates this more accurately:
Here you can see that test actually becomes a property of the array, like the length property rather than array element.
All of this is nothing new, but the nuances of array management in Javascript takes some getting used to and occasionally they end up tripping me up. I know I’ve used all of those features of arrays before so I took the opportunity here to write it down as a note to self. Hopefully some of you new to Javascript may find this useful.
Other Posts you might also like