DEV Community

Cover image for Yes, {} + [] = 0. No, JavaScript Isn’t Broken
Sylwia Laskowska
Sylwia Laskowska Community Curator

Posted on Edited on

Yes, {} + [] = 0. No, JavaScript Isn’t Broken

Born from airport boredom and spec quirks

JavaScript is a legendary programming language. Created in the mid-1990s in just 10 days, it was born during the browser wars, when Netscape was trying to deliver a fatal blow to Microsoft. As we all know, that didn't exactly work out as planned… Today, some people love JavaScript, others hate it, and some just make fun of it. But the truth is, the modern web simply wouldn't exist without it!

Over the years, JavaScript has gone through countless revolutions. Its capabilities today are almost incomparable to what the language could do back in the 1990s. There's just one tiny problem… Every change to the language has to take into account the fact that millions of websites out there still rely on old JavaScript behavior. And some of those websites will probably continue running that code until the end of time.

So, well, JavaScript's weirdness is probably here to stay forever! 😂

After quite a long break, I've decided to bring back my once-popular JS WTF series. For a very simple reason. I'm on my way back from iJS Munich, and I still have two hours to kill at Frankfurt Airport… (don't ask). Not enough time to write a groundbreaking, deeply technical article. But definitely too much time to just sit here and stare at the wall.

So let's take a look at one of my favorite JavaScript constructions:

{} + [] // 0
Enter fullscreen mode Exit fullscreen mode

Yes, you read that correctly. Under the right circumstances, if we add an empty object to an empty array in JavaScript, we get zero. And it makes perfect sense! 🤡

Wait, what? Why does this happen?

The first thing you need to know is that JavaScript doesn't necessarily interpret {} as an object in this situation! Depending on the context, the JavaScript parser can treat the expression as two completely separate things.

Consider this code at the beginning of a statement in a classic JavaScript script:

{} + []
Enter fullscreen mode Exit fullscreen mode

JavaScript can interpret it like this:

{}    // An empty block of code
+[]   // Unary plus applied to an empty array (what could go wrong?)
Enter fullscreen mode Exit fullscreen mode

That's right. The first {} isn't an object literal at all. It's simply an empty block of code that does absolutely nothing. And the second part? Well, that's where the fun begins.

The magic of type coercion ✨

The expression:

+[]
Enter fullscreen mode Exit fullscreen mode

is a classic example of type coercion, one of the things our wonderful language is famous for.

As you probably know, JavaScript is a dynamically and weakly typed language.

Dynamic typing means that variables aren't permanently tied to one type. You can assign a number to a variable and then replace it with a string, and JavaScript won't complain.

But there's more! JavaScript also performs implicit type conversions, which is one of the reasons it's often described as weakly typed. And sometimes those conversions produce rather… creative results.

Take our unary plus operator:

+[]
Enter fullscreen mode Exit fullscreen mode

Unlike the binary + operator, which can add numbers or concatenate strings, unary plus tries to convert its operand into a numeric value. In this case, it behaves essentially like:

Number([])
Enter fullscreen mode Exit fullscreen mode

Yes, we're trying to convert an array into a number. Because why wouldn't we?

But before JavaScript can complete this operation, it needs to perform another conversion. An array is an object, and JavaScript first needs to obtain a primitive value from it. For an ordinary empty array, that process ends up calling its toString() method.

And guess what?

[].toString(); // ""
Enter fullscreen mode Exit fullscreen mode

An empty array becomes an empty string.

So our conversion effectively looks like this:

Number([]);

// First, the array becomes a primitive string:
Number("");

// Then, the empty string becomes:
0
Enter fullscreen mode Exit fullscreen mode

Because:

Number("") // 0
Enter fullscreen mode Exit fullscreen mode

And therefore:

+[] // 0
Enter fullscreen mode Exit fullscreen mode

Which means our original construction:

{} + []
Enter fullscreen mode Exit fullscreen mode

when parsed as an empty block followed by unary plus, effectively becomes:

{} // Do absolutely nothing

+[] // 0
Enter fullscreen mode Exit fullscreen mode

And that's how we get zero! Simple and obvious, right? 🤡

To be fair, I can't think of another language where exactly this construction would produce such a perfectly normal-looking result. Even our beloved PHP would, I believe, throw a fatal error for something like this. Although PHP has its own collection of fascinating surprises, so perhaps we shouldn't judge too harshly.

One important detail: this behavior depends on how the code is parsed. For example:

// In a classic script, as a standalone statement:
{} + [] // 0

// Force JavaScript to interpret {} as an object:
({} + []) // "[object Object]"

// Inside a function call:
console.log({} + []); // "[object Object]"
Enter fullscreen mode Exit fullscreen mode

Okay, but what about [] + []?

Now that you understand type coercion, this one should be obvious:

[] + [] // ""
Enter fullscreen mode Exit fullscreen mode

Here we're dealing with the binary + operator. JavaScript converts both arrays into primitive values. Well, what else would you expect when adding two empty strings together? 😀 Nothing plus nothing equals nothing! Beautiful.

And now, apparently, addition isn't even commutative 😂

Following the same logic, let's try another expression:

[] + {} // "[object Object]"
Enter fullscreen mode Exit fullscreen mode

Wait a minute.

Didn't we just establish that:

{} + [] // 0
Enter fullscreen mode Exit fullscreen mode

So why does reversing the operands give us something completely different? Apparently, even the commutative property of addition is optional in JavaScript. xD

Well, technically, we're not always performing mathematical addition here, and the parser treats these expressions differently.

But let's not ruin a good joke with technical details. Here's what actually happens. In this expression:

[] + {}
Enter fullscreen mode Exit fullscreen mode

The empty array becomes an empty string:

[].toString() // ""
Enter fullscreen mode Exit fullscreen mode

And the empty object? Well, a regular JavaScript object has its own wonderful string representation:

({}).toString() // "[object Object]"
Enter fullscreen mode Exit fullscreen mode

So JavaScript effectively performs:

"" + "[object Object]"
Enter fullscreen mode Exit fullscreen mode

Which gives us:

"[object Object]"
Enter fullscreen mode Exit fullscreen mode

And that's it! Simple as building a flail. Okay, that's a literal translation of a Polish saying, proste jak budowa cepa, which means something is ridiculously easy to understand. And I think it fits JavaScript perfectly. 😂

Final thoughts

I hope you enjoyed this little journey into the wonderful world of JavaScript weirdness. And I hope that after reading this article, you'll appreciate the beauty and originality of this magnificent language even more.

After all, JavaScript has been keeping us entertained for over 30 years, and I strongly suspect it has plenty of surprises left.

And the best part? None of the examples above are bugs. They're all consequences of JavaScript's parsing rules, type coercion, and the language's long history of backward compatibility. So next time someone tells you JavaScript is broken because {} + [] can equal 0, you can proudly explain why it makes perfect sense.

Next time I'll tell you why {} + {} = NaN... but unfortunately time flies when you're having fun, and I'll have to get ready for my flight soon!


P.S. If you enjoy my content, feel free to connect with me or leave a like on LinkedIn! ❤️

Top comments (121)

Collapse
 
sylwia-lask profile image
Sylwia Laskowska •

Ok, see you folks! 😆
airplane

Collapse
 
georgekobaidze profile image
Giorgi Kobaidze •

My aviation nerd eyes instantly spotted the Lufthansa logo 😄

Nice article by the way!🔥

Collapse
 
sylwia-lask profile image
Sylwia Laskowska •

Thank you so much! Hahaha, Giorgi, you're right, the logo is actually there! You've got a good eye! Although I have to say, I feel like Lufthansa has gone a bit downhill lately, and these days I actually prefer Polish LOT! 😄

Thread Thread
 
georgekobaidze profile image
Giorgi Kobaidze •

Yeah, I've noticed that too. It's closer to a budget airline than a luxury one.
I haven't flown with LOT Polish Airlines though.

Thread Thread
 
sylwia-lask profile image
Sylwia Laskowska •

Hahaha, on LOT you even get a sweet bun! And seriously, it's actually pretty good! I think they bake them fresh regularly. You can also get beer or wine in a plastic cup. 😅 Although on some flights they seem to keep that a secret, and you have to know to ask for it! 😂 I usually go for the wine, but there's always that fear that one unexpected bout of turbulence will leave me completely covered in it. XDDD

Thread Thread
 
georgekobaidze profile image
Giorgi Kobaidze •

You folks are on fire! A great country with an airline THAT good... Poland is really out there going for being the best country in Europe. And it's working. 😄

Thread Thread
 
sylwia-lask profile image
Sylwia Laskowska •

Hahaha, who knows! 😄 Just yesterday, while I was in Munich, I was thinking that we really have no reason to feel inferior to Western Europe anymore! :) So you're more than welcome!

Thread Thread
 
georgekobaidze profile image
Giorgi Kobaidze •

Totally true, as much as I love Germany and Munich, I've noticed quite a lot of things that needs to be addressed as soon as possible. Western Europe definitely needs to wake up a little bit.

Same goes to my country, but we've been sleeping for decades already, so there's no hope🤣

Thread Thread
 
sylwia-lask profile image
Sylwia Laskowska •

Yeah, it's actually really sad to see what's happening in Georgian politics. :( Especially since Georgia is such a beautiful country! I'd absolutely love to visit again, especially Batumi! And I still haven't made it to Mount Kazbek! 😄

Thread Thread
 
georgekobaidze profile image
Giorgi Kobaidze •

Yeah, it’s pretty bad right now…
I’ve never been to Kazbek, BTW. And I’ve been to Batumi just once.

I don’t really travel inside the country, I’m way too busy. Every time I had to leave the city was because of… you’re right - work😂

Thread Thread
 
sylwia-lask profile image
Sylwia Laskowska •

Hahaha, there's definitely something to that! There are so many beautiful places in Poland that I haven't visited either. Whenever I go on vacation, I often end up going abroad instead. I guess I'll catch up on exploring my own country when I retire! 😅

Thread Thread
 
georgekobaidze profile image
Giorgi Kobaidze •

Well, I'm never gonna retire so I guess Georgia stays unexplored forever lol

Thread Thread
 
sylwia-lask profile image
Sylwia Laskowska •

Giorgi, but retirement isn't the end of life! 😂 In Munich, I met a guy who's a pretty big name in the Angular world, and he told us that, as part of his midlife crisis, he'd become the maintainer of several abandoned libraries. I'm almost afraid to imagine what he'll start doing when he retires! 😂

Thread Thread
 
unitbuilds profile image
UnitBuilds •

I lost trust in Lufthansa... My fiance was flying through Frankfurt, but got detoured to Munich due to 'balloons' at the airport, that's fine, but the entire time in Munich, they had the onboard wifi (which I paid for), switched off, so she had no way to communicate with me, I had to check flightradar to even know where in the world she is. And that doesnt even cover the fact that they got her meal wrong (I booked her as vegetarian), the flight crew were rude and the entire time they were grounded in munich, they didnt even offer passengers water. Definitely not the lufthansa I grew up with...

Thread Thread
 
sylwia-lask profile image
Sylwia Laskowska •

Oh damn, I'm so sorry to hear that! 😞 But yes, Lufthansa really isn't what it used to be. I remember thinking it was one of the best airlines in the world! I'm going to Berlin next month, and honestly, I think I'll just take the train this time! 😂

Thread Thread
 
unitbuilds profile image
UnitBuilds •

Trains are nice, you get to see alot more of the countries than you do from even a window seat (sounds counter intuitive). Not to mention, the food is alot better 😂 And cant complain about the legroom either!

Thread Thread
 
unitbuilds profile image
UnitBuilds •

But yeah, it was quite scary, because we were on call, she just said 'wait there's something happening' listens to the intercom, tells me 'there's something about terrorists?' and then the onboard wifi cut... Turns out protestors at the frankfurt airport set off a bunch of balloons in protest of germany's involvement with the ukraine war. Then they went up to altitude again, the wifi went on, she told me that she's okay and that they're detouring to munich, landed, then radio silence for 3 hours... They werent allowed to leave the plane either. Then back in the air to frankfurt and she let me know that she's fine again.

Not a nice feeling having the person you care most for in the world, 10k km away and those are the snippets you hear. I was frantically searching the web for answers on what's going on, where is she, is she okay, is the plane safely landed, etc. Her parents were also freaked out, so I had to be liaison to them for any info on her flight.

Thread Thread
 
georgekobaidze profile image
Giorgi Kobaidze •

I love trains.

Thread Thread
 
georgekobaidze profile image
Giorgi Kobaidze •

That’s also true😄

Collapse
 
mohamed_mahmoud_32383bd38 profile image
Mohamed Mahmoud •

I wish you a pleasant trip 🙂

Collapse
 
luke_bennett_ed52405c798e profile image
Comment marked as low quality/non-constructive by the community. View Code of Conduct
Luke Bennett •

I gogoled this that is the meeting that is the meeting weekend problem a nice day soon please send me the address club i gogoled this that is the meeting weekend as tomorrow sorry very much doing soon job a good weekend xxDzxd
14 stones 2.416 pounds

Collapse
 
francistrdev profile image
FrancisTRᴅᴇᴠ •

This is the most JavaScript thing I've seen, and I am not disappointed XD

Collapse
 
sylwia-lask profile image
Sylwia Laskowska •

Hahaha, Francis, this is just the tip of the iceberg when it comes to JavaScript weirdness!

Collapse
 
mikky_986f0099d2222a profile image
Comment marked as low quality/non-constructive by the community. View Code of Conduct
Mikky •

Hello.
How are you?
Can we collaborate with us?
Please let me know if you’d be open to chatting.
I look forward to hearing from you.
Best regards

Collapse
 
xulingfeng profile image
xulingfeng •

That’s weird. I never get notifications for your posts. I only found this fantastic article more than ten hours late. Must be a bug on Dev.to!😂😍

Collapse
 
sylwia-lask profile image
Sylwia Laskowska •

Hahaha, who knows, maybe it's all part of some conspiracy! 😂

Collapse
 
kenwalger profile image
Ken W Alger •

JavaScript is one of those languages where you can explain exactly why something happens, walk through every step of the specification, demonstrate that the implementation is behaving correctly, and still conclude that the language has made some questionable life choices.

The distinction between {} + [] and ({} + []) is particularly entertaining. Same characters, different parsing context, entirely different result.

Glad to see the series back! If this is what two hours at Frankfurt Airport produces, perhaps longer layovers should be encouraged.

Collapse
 
sylwia-lask profile image
Sylwia Laskowska •

Hahaha, exactly! Everything makes sense, everything has a perfectly logical explanation, and yet it never stops being funny, even after all these years!

And as for airports, I actually quite enjoy writing there! It's only when I'm at an airport that I realize just how much time writing articles really takes. Somehow, when I'm at home, I don't notice it nearly as much. 😂

Collapse
 
pengeszikra profile image
Peter Vivo •

Hi Sylwia! JS is my favorite programming language, as you know, since Adobe killed Flash. But honestly, JS is better because it’s free to use. Maybe you could try TDM = Travel Development Method, which is also a vibe coding aberration. It means nothing more than programming while travelling. By the way, I’m happy to have found a similar concept in UMGD.

But let’s get back to JS. I’m a really big fan of it, which is why I argue for JSDoc instead of TS. These positive feelings also led me to create mordorjs, which, at the end of the day, is pure JS. It just uses a strange ability of JS that lets you write working code in a one-character-wide format.

Collapse
 
sylwia-lask profile image
Sylwia Laskowska •

Hahaha, Peter, yes, I know how much you love JavaScript! I personally use TypeScript, but I totally get your point!

Actually, just the day before yesterday, I was chatting with some fellow developers in Munich, and we started reminiscing about the old days when TypeScript was just emerging. I remember we were a bit hesitant to adopt it because, well, what if Microsoft decided to abandon the project?

But what eventually convinced us was that TypeScript compiled down to pretty clean, readable JavaScript. That was our main argument: we could always go back to that slightly crazy but beautiful language!

Collapse
 
pengeszikra profile image
Peter Vivo •

Right now thanks to open script behiaviour of TypeScript any one can fork it, and make it own verison with own solution, so right now TS is bit versatile compared to JS, there is need to wait a new upgradding in every years.

Collapse
 
gramli profile image
Daniel Balcarek •

Only JavaScript developers can spend 10 minutes explaining why {} + [] equals 0 and then proudly say, “See? It makes perfect sense!” 😂

I think that’s called Stockholm syndrome. 🤣

Just kidding! Great article, even this backend developer enjoyed reading it! 🤣

Collapse
 
sylwia-lask profile image
Sylwia Laskowska •

Hahaha, thank you! 😂 And yes, that's exactly how it works! I think they should use this article in psychology classes to illustrate Stockholm syndrome, so students can truly understand just how serious this condition is! 😂😂😂

Collapse
 
nyaomaru profile image
nyaomaru •

JavaScript has so many deep parts or maybe shallow parts? 😹

I always find it funny how something as simple as an empty object and an empty array can behave so differently depending on how the parser sees them.

These little quirks are one of the reasons JavaScript keeps surprising us. 🐟

As always, your article was really easy and fun to read!

Have a safe trip home! ✈️😸

Collapse
 
sylwia-lask profile image
Sylwia Laskowska •

Aww, thank you! ❤️ I'm already back home! :) And exactly! This kind of knowledge probably won't be very useful in our everyday coding. Although I remember there was (and I think there still is) a website called Return True to Win, where knowing these weird JavaScript tricks actually came in handy!

I remember joking with my colleagues at work that one day we'd give someone those challenges during a job interview. And then, a few years later, someone actually gave me one of those challenges in an interview! 😂

Collapse
 
nyaomaru profile image
nyaomaru •

Haha, that’s amazing 😹
The fact that a joke challenge came back as a real interview question years later is peak JavaScript. 😹

And glad you made it home safely! 😸

Thread Thread
 
sylwia-lask profile image
Sylwia Laskowska •

Thank you! By the way, funny story: I actually didn't get that job! And those were very different times. The job market wasn't nearly as competitive as it is today, and if you were a good developer, finding a job was relatively easy.

I actually did pretty well in that interview, but they rejected me because they thought I wasn't... senior enough, and that junior developers wouldn't respect me. XDDD

Which is especially hilarious now, when junior developers sometimes call me five times a day with every possible question imaginable! 😂

Thread Thread
 
nyaomaru profile image
nyaomaru •

I’m honestly surprised you didn’t get the job! 😹

If I were the one hiring, I think I would’ve hired you.

And knowing that juniors now call you five times a day makes the story even funnier. 😹

Thread Thread
 
sylwia-lask profile image
Sylwia Laskowska •

Hahaha, thank you! 😄 But honestly, it all worked out for the best in the end!

Collapse
 
shubhradev profile image
Shubhra Pokhariya •

Imagine explaining this in a code review: "No, the empty block isn't useless. It's what gets us zero 😂" Also love that adding just one pair of parentheses makes JavaScript treat {} as an object. Can't wait for the {} + {} one, Sylwia!

Collapse
 
sylwia-lask profile image
Sylwia Laskowska •

Hahaha, I doubt it would even make it to code review! More likely, someone would be sitting there wondering, "Why the hell isn't this code working?!" 😂

Collapse
 
varshithvhegde profile image
Varshith V Hegde • • Edited

Javascript is such a fun language it makes me frustrated everytime 😂

Collapse
 
sylwia-lask profile image
Sylwia Laskowska •

You're not the only one! 😂

Collapse
 
varshithvhegde profile image
Varshith V Hegde •

It's kind of love hate relationship 😂😂

Thread Thread
 
sylwia-lask profile image
Sylwia Laskowska •

Hahahaha exactly 😂😂😂

Collapse
 
sinarezaei profile image
Sina Rezaei •

One thing worth remembering is that JavaScript's object semantics can become a production security issue, not just a source of funny console output.

There's a good example in qs (CVE-2026-82417). An attacker could influence an object's shape through query parameters, and later qs.stringify() would try to invoke constructor.isBuffer without checking whether it was actually callable. That could trigger a TypeError and cause a DoS.

It's a different edge of JavaScript than {} + [], but the underlying lesson is similar: what looks like a perfectly ordinary object isn't necessarily what the next operation expects.

That's why I think understanding these language rules matters beyond passing a JavaScript interview.

Collapse
 
sylwia-lask profile image
Sylwia Laskowska •

Oh, I didn't know about this one! But that's exactly the thing with JavaScript. It's not always just about funny console tricks. Sometimes making assumptions about objects can have some really serious consequences!

Collapse
 
sinarezaei profile image
Sina Rezaei •

There's another interesting edge case with coercion: Symbol.toPrimitive. It's not just about how an object gets converted to a string or number. An object can actually control what happens during that conversion.

I've seen this become particularly relevant with custom value objects in financial systems. Imagine a Money object used in a calculation, but its primitive conversion returns a formatted string for display. Suddenly, an expression like total + amount can switch from numeric addition to string concatenation, depending on which object is involved.

That's one reason I prefer explicit methods like money.add(other) and money.toMinorUnits() over relying on implicit conversion. The language is doing exactly what the spec says, but the business logic might be doing something completely different from what the developer intended.

Thread Thread
 
sylwia-lask profile image
Sylwia Laskowska •

Exactly! Symbol.toPrimitive is a really useful feature, especially when you want explicit control over how objects are converted to primitive values. But interestingly, it was only introduced in ES6, back in 2015. Meanwhile, weird behaviors like {} + [] have their roots in the earliest days of JavaScript, when the language was famously put together in a rush. And decades later, we're still living with some of those decisions! 😂

Thread Thread
 
sinarezaei profile image
Sina Rezaei •

That's an interesting distinction. The coercion mechanism itself is much older, but Symbol.toPrimitive made the conversion hook explicit and gave objects more control over it.

One less obvious place where this matters is property-key conversion. Consider an object used as a dynamic key:

const key = {
  [Symbol.toPrimitive]() {
    return "__proto__";
  }
};

const config = {};
config[key] = { isAdmin: true };
Enter fullscreen mode Exit fullscreen mode

The assignment implicitly converts key into a property key. It doesn't remain an object reference. In this case, it resolves to "__proto__", which interacts with the inherited prototype setter rather than behaving like an ordinary data key.

This alone isn't a complete prototype pollution vulnerability, but in a system that dynamically builds configuration objects from values crossing plugin or extension boundaries, these conversion rules become part of the security surface.

That's why I think coercion deserves more attention than it usually gets. The interesting part isn't just what value an expression returns, but what operations JavaScript executes to get there.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.