DEV Community

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

Posted 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 (30)

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🤣

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
 
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
 
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! 😸

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
 
benrrr profile image
Brrrrr •

JS being JS

Collapse
 
sylwia-lask profile image
Sylwia Laskowska •

How not to love it 😅

Collapse
 
effessdev profile image
EffessDev • • Edited

This is why I always write everything explicitly 😅 It's not a problem as long as we avoid it right?

Collapse
 
sylwia-lask profile image
Sylwia Laskowska •

Exactly! That's one thing! 😅 I also use TypeScript and linters to keep me (or my coding agent) in check whenever we get a little careless. Do you use TypeScript too?

Collapse
 
effessdev profile image
EffessDev • • Edited

I only use TypeScript (I literally forgot JavaScript lol), and I'd never do something like {} + [] (too risky 😬😅)

Collapse
 
robertpaschal profile image
Odinaka Robert Nnamani • • Edited

The sneaky part is +[] detouring through "" on its way to 0, same reason an empty form field sails past a Number() check

Collapse
 
sylwia-lask profile image
Sylwia Laskowska •

Exactly! 😂 JavaScript has been turning empty things into zero for 30 years, and we're still finding new ways to get surprised by it.

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
 
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!