My personal little JavaScript WTF

This post is more than 2 years old.

There are presentations and even a website dedicated to JavaScript oddities. I'm sure this one I ran into has been discussed before, but it certainly surprised me.

I wrote a little function that I thought was pretty trivial. Given a set of objects, iterate over them, check some value, and if good, append matches to an array. Here is an example of what I wrote.

When I ran my code, I kept getting a 0-length array back. I added a simple variable inside my condition and confirmed that it was matching and appending those matches, so... wtf?

Some of you probably see it right away. It took me a good twenty minutes of frustration before I saw it. See the push call? I used brackets instead of parenthesis. I have no idea why this didn't throw an error and I'd love to know why. Ok, JavaScript gurus, can you explain this one?

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Shawn Biddle posted on 1/1/2014 at 12:20 AM

I have no idea why this didn't throw an error and I'd love to know why. Ok, JavaScript gurus, can you explain this one?

Functions are objects, [] is notation to access properties of an object which is sugar'd by . notation (foo['bar'] === foo.bar) (in addition to array access), push[something] simply tries to access a key that doesn't exist, this will not throw an error, it will simply return undefined

Comment 2 by John C Bland II posted on 1/1/2014 at 12:31 AM

Functions have methods on them; is - array.push.apply(...).

You can dynamically access them like: array.push["apply"](...).

So by using brackets and pushing an invalid function name in there you were simply trying to access something that didn't exist. Log it and you'd get an undefined.

Comment 3 by Raymond Camden posted on 1/1/2014 at 12:31 AM

Makes sense - thanks both of you.

Comment 4 by John C Bland II posted on 1/1/2014 at 12:32 AM

Oh, Shawn said the same thing. I didn't see his. Lol

Comment 5 by Raymond Camden posted on 1/1/2014 at 12:32 AM

Sad thing is - I *knew* this too - just... forgot I suppose. :)

Comment 6 by John C. Bland II posted on 1/1/2014 at 1:09 AM

I figured it'd make sense once you saw it since it is the same for dynamic access in CF.

Comment 7 by Axel Rauschmayer posted on 1/1/2014 at 7:00 AM

obs.push is an object and you access one of its properties via the square brackets. The WTF part of the thing is that *everything* in square brackets is converted to string, even array indices. That is, the spec (as opposed to JavaScript engines) interprets array indices as strings and has rules for their shapes [1].

You can use String() as a function to check how the conversion to string is performed.

[1] http://www.2ality.com/2012/...

Comment 8 by Dumitru "Mitic?" UNG posted on 1/1/2014 at 3:43 PM

obs is an Array and it's also an Object.

What this means is that beside taking index values, it accepts properties like any other Object, including other Objects: push, which, in return, have properties of their own: [something].

http://jsfiddle.net/cfjedim...

<iframe width="100%" height="300" src="http://jsfiddle.net/cfjedim..." allowfullscreen="allowfullscreen" frameborder="0"></iframe>

Comment 9 by Dumitru "Mitic?" UNG posted on 1/1/2014 at 3:44 PM

WTF jsFiddle link :)

http://jsfiddle.net/Su9eh/2/

Comment 10 by Raymond Camden posted on 1/1/2014 at 7:14 PM

Dumitru - all HTML is escaped for security reasons here.

Comment 11 by Dumitru "Mitic?" UNG posted on 1/1/2014 at 10:08 PM

OK :)

Anyway, Shawn Biddle is spot on. I just wanted to remind us about the "almost everything is an object in JavaScript".