My personal little JavaScript WTF

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?

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".