Skip to content
DevMeme
5398 of 7590
Languages Post #5917 · source on Telegram

JavaScript's Infamous Octal Number Quirk

Description

This is a two-panel meme that perfectly captures a frustrating and non-intuitive aspect of JavaScript. The top panel shows a code editor with a JavaScript file named 'index.js'. The code consists of two lines: `console.log(018 == '018');` and `console.log(017 == '017');`. The terminal output below shows 'true' for the first line and 'false' for the second. The bottom panel features a still from the game Team Fortress 2, with two characters laughing hysterically, captioned with 'JavaScript Moment'. The technical humor lies in JavaScript's legacy handling of octal (base-8) literals. A number starting with a zero (like 017) is treated as octal. Since octal only uses digits 0-7, `017` is valid octal for the decimal number 15. However, `018` is an invalid octal number, so JavaScript silently treats it as the decimal number 18. When using the loose equality `==` operator, `18 == '018'` coerces to `18 == 18` (true), while `15 == '017'` coerces to `15 == 17` (false). This counter-intuitive behavior is a classic 'gotcha' that leads to bugs and developer frustration

Comments

63
Anonymous ★ Top Pick JavaScript's loose equality is the reason code reviews exist. It's the only place where `017` being unequal to `'017'` is somehow logical
  1. Anonymous ★ Top Pick

    JavaScript's loose equality is the reason code reviews exist. It's the only place where `017` being unequal to `'017'` is somehow logical

  2. Anonymous

    JavaScript Annex B: 017 time-travels to octal 15, 018 gets deported back to decimal, and your diff suddenly looks like a PDP-11 permissions audit

  3. Anonymous

    After 20 years in the industry, you'd think we'd all remember to use strict mode by now - but no, we're still discovering that JavaScript treats 018 as decimal because even octal numbers have standards, while 017 happily becomes 15 in base-10. It's like finding out your production config parser has been silently misinterpreting UNIX file permissions for years

  4. Anonymous

    Ah yes, the classic '018 == "018"' returns true but '017 == "017"' returns false - because JavaScript sees that leading zero on 017 and thinks "ah, octal!" converting it to decimal 15, while 018 is an invalid octal (no 8 in base-8) so it just shrugs and treats it as decimal 18. This is why we have 'use strict' and ESLint rules, folks. Nothing says 'battle-tested language design' quite like having to explicitly disable footguns from 1995

  5. Anonymous

    In JS, leading zeros are a time machine: 017 is octal 15, 018 is decimal, and '==' smiles through it - use strict modules or stop zero-padding like it’s 1995

  6. Anonymous

    Loose equality is fine - until a single leading zero from a CSV turns billing into base‑8 and on‑call into exponential backoff

  7. Anonymous

    JS octals: valid only sans '8', because who needs consistent parsing when you have history to honor?

  8. @flyingshine 2y

    still better than python

    1. @Iggdraisil 2y

      Have you ever seen Python moments like that?

      1. @flyingshine 2y

        ahahaa so funny, silly python developers😂

      2. @karumsenjoyer 2y

        how often you write shitty code like that?

      3. @Terroo 2y

        Bruh That's literally gh repo about python moments https://github.com/satwikkansal/wtfpython

      4. @ZgGPuo8dZef58K6hxxGVj3Z2 2y

        Try using both spaces and tabs

    2. @Johnny_bit 2y

      That's one way to start a flamewar...

  9. @HeTema 2y

    Why first one is true and second one is false?

    1. @Agent1378 2y

      Probably, because of leading zero second is treated like it is base 8

  10. @vladislav805 2y

    017 (oct) = 15 (dec) 018 = 18

    1. @purplesyringa 2y

      I think the weird part is that "017" is implicitly converted to 17 instead of 15

      1. @azizhakberdiev 2y

        ig these conversions aren't considered thoroughly. For binaries and hexadecimals it works well. parseInt however recognizes only hexadecimals

    2. @FlyLikeSoarin 2y

      Why would base 8 literal with 8 in it be treated as anything other than error... This language is cancer

      1. @deadgnom32 2y

        2.3.1 An integer constant is a sequence of digits. An integer is taken to be octal if it begins with 0, decimal otherwise. The digits 8 and 9 have octal value 10 and 11 respectively.

      2. @deadgnom32 2y

        in old C it wasn't an error either

        1. @FlyLikeSoarin 2y

          Day ruined

          1. @Agent1378 2y

            Surprised?

            1. @FlyLikeSoarin 2y

              Yeah, a little bit. I would've been less surprised if 018 somehow did something unexpected in modern c++ with all of its bloat. The more you know

              1. @Agent1378 2y

                C is the same junks as JS, it was called "assembly for lazy people". Maybe it is better now but doubt it - CVEs still come in every day

                1. @FlyLikeSoarin 2y

                  I think that in terms of security any maintained language that gets its vulnerabilities fixed in timely manner is as good as any other. For me C is not the same junks as JS, but it is an opinion. In the end of the day it all comes down to personal preference and the problem that needs to be solved.

                  1. @Agent1378 2y

                    A lot of vulnerabilities should not have appeared in the first place. A little bounds check by compiler, a little type safety would do. But no, people still think it is all "makes code slow" (in places where this doesn't matter) and compile with no checks and etc.

    3. @Supuhstar 2y

      018 isn't valid octal tho 😭😭😭 it should reject it with an error

  11. @heygambo 2y

    018 is not a valid octal number and javscript will treat it as a decimal number as a fallback. better would be to maybe throw an error I suppose

  12. @heygambo 2y

    https://www.youtube.com/watch?v=FhNwLvCYlY4

  13. @casKd_dev 2y

    octal vs decimal?

  14. @IHateCupsAndDonuts 2y

    455 257 weekly installations <3

  15. @avrdudec 2y

    let’s pretend static comparison doesn’t exist

    1. Deleted Account 2y

      омагааах

    2. @ovarn 2y

      Something was changed in the V8 a couple years ago, if I am not mistaken. Where did you execute it?

      1. @purplesyringa 2y

        It's not V8, it's == vs ===

        1. @ovarn 2y

          Oh, I see

  16. @SamsonovAnton 2y

    It still baffles me that so many programming languages use line breaks [as end of statement] to tokenize the code. 🤓

  17. @SamsonovAnton 2y

    Your cryptic message looks like some shell script bomb.

  18. @Kyngo 2y

    this is actually intended to be like that, i don't see the problem with this

  19. @Sp1cyP3pp3r 2y

    Programming languages for pussies, use runes

    1. @AmindaEU 2y

      I would like to hear more 👀

  20. @deadgnom32 2y

    why?

  21. @misesOnWheels 2y

    Classic "I have no fucking clue how my programming language works so I'll make fun of it" moment

  22. @deadgnom32 2y

    because of more syntactic noise? nonsense. you just got used to it. let me bring an example

  23. @deadgnom32 2y

    what is simpler to read?

  24. @deadgnom32 2y

    foo x = let s = sin x c = cos x in 2 * s * c

  25. @deadgnom32 2y

    or

  26. @deadgnom32 2y

    foo x = let { s = sin x; c = cos x; } in 2 * s * c

  27. @deadgnom32 2y

    if your code is small enough, then all those curly and round braces are just noise. imagine it to be folded like multiple times, then instead of a couple of lines of information we will have a lot of curly braces that get opened and closed. another example what is easier to read? f1(f2(f3(f4(x)))) or f1 . f2 . f3 . f4 x

    1. @deadgnom32 2y

      it's about, the thing, that with more experience you need less syntax for short concise solutions

  28. @deadgnom32 2y

    why?

  29. @deadgnom32 2y

    it has more syntax you don't need to understand either way. and formatting is more machine readable rather than human readable.

  30. @deadgnom32 2y

    it's about using right tools for right tasks. i know there are huge monolith python projects out there and its a pain to work with them. but if you just need a small script like <1000lines. it's even easier to comprehend if it has less syntactic noise.

  31. @deadgnom32 2y

    for composition too

  32. @deadgnom32 2y

    yeah. people just take Java and write 10000 lines of SOLID code, while the same fits in a mere 200 lines of SQL script

  33. @deadgnom32 2y

    for example, how to reduce the amount of lines of code by more than 10 times? throw away ORM. even in python SQL code like: CREATE TABLE id_table(id INTEGER PRIMARY KEY); a minimal table. requires this much of code from sqlalchemy import Column from sqlalchemy import Integer from sqlalchemy.orm import DeclarativeBase class Base(DeclarativeBase): pass class IdTable(Base): __tablename__ = "id_table" id = Column(Integer, primary_key=True)

    1. @deadgnom32 2y

      and it even doesn't provide a proper type hints. I'm really unable to comprehend the advantage. it doesn't provide even type hinting it requires different code for different data bases... so it has all the disadvantages of the pure sql solution, but the more complex it gets, the harder it is to use the ORM compared to pure SQL. my last experience with it was to drop the development of the data model after 250 lines and 3 days of complicated OOP code. and then solve the task in 16 lines and a couple of minutes of declarative code.

  34. @FunnyGuyU 2y

    JS was initially designed to execute any crap, any ravings of any madman at any cost. All subsequent evolution of this monstrosity is no more than futile attempts to formalize it ang ram some logical explanations of its behavior down our throats.

  35. @AlexAparnev 2y

    still better than excel

  36. Ricardo Gross 2y

    Wow, this post definitely caught my eye. Cant wait to see more from you. 😉

  37. @colllapse 2y

    not really js moment. C did this too back in a day.

Use J and K for navigation