Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

Javascript Array Fun


:P
On this page:

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):

 array[4]

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:

 Array2

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:

 VsArray

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.

Posted in JavaScript  

The Voices of Reason


 

Piersh
January 27, 2009

# re: Javascript Array Fun

There's a great couple of posts on the jscript blog (http://blogs.msdn.com/jscript ) covering recent array optimizations. It goes into detail about sparse/contiguous arrays are implemented and the performance implications of using them... (sorry, no copy/paste on iPhone)

Jose Silva
January 27, 2009

# re: Javascript Array Fun

Imagine this code:

function test()
{
    alert('hello');
}


What happens if you call
window.test()

And what happens if you call
window['test']()


In short, we must always think that Javascript objects are a dynamic set of properties containing values or functions. Every object is stored in the parent object and is accessible directly (window.test()) or through a hash (window['test']()).

Keep up the good work.

Rick Strahl
January 27, 2009

# re: Javascript Array Fun

@Jose - yes that's what's happening in the last example with the string based 'indexer'. Expando properties and can be created via new property assignments or the string 'indexer'. The same holds true for arrays but it's one of those things easy to miss because you'd expect any indexer on array to create an array element which it does not.

Steve from Pleasant Hill
January 27, 2009

# re: Javascript Array Fun

With "fun" like this, no wonder I get JS errors with IE6 on so many pages I browse...

Matt
January 28, 2009

# re: Javascript Array Fun

What about this?

var ar = [];
ar[0] = "index";
ar["0"] = "index?";
var len = ar.length;
debugger;


I guess it works the way you would expect:

var index = "0",
    assertThis = (ar[index] === "index?");
debugger;


That is, you wouldn't want to use an indexer variable (containing a number that *might* be a JavaScript string) that could give you varying results depending on its type at that point in time!

Jason
December 27, 2010

# re: Javascript Array Fun

if you call
window.test()

if you call
window['test']()


how can i know which function can be invoked by using the above way?(how can i get the hase keys)

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024