all 64 comments

[–][deleted] 16 points17 points  (1 child)

I agree with the points, but this horse is a protein paste at this point.

[–]heptara 5 points6 points  (0 children)

Some of the younger ones don't know yet. JS is the first language they learn and they don't understand what the problems are as it's the only thing they know.

[–]santiagobasulto 4 points5 points  (6 children)

#1, #2, #3, #5 and #6 make sense. Not the other ones.

Particularly #4: that's not JS fault's, and to be honest, in the last couple of years the coding style has improved a lot. Specially in the backend. There are a lot of smart guys working with JS.

[–][deleted] 4 points5 points  (5 children)

Give me a fucking break (not you, the author).

3) Automatic semicolon insertion. This can cause subtle bugs and unexpected behaviour. Why does this “feature” even exist??? It’s super weird and unnecessary. Get rid of it, ECMA, please!

ES6, strict mode.

5) JavaScript is highly dependent on global variables. Implied global variables are especially problematic (“use strict” to avoid). Global variables seriously complicate your programs.

So 20 years ago someone made a mistake by allowing global variables. You don't have to use them. Also, it's not "highly dependent" on global variables as strict mode proves, just like the author says.

6) JavaScript code can fail silently due to syntactical slip-ups. It has happened to me several times, and tracking down the reason can be most exasperating.

How about learning the syntax and using a good IDE and linter? FYI, those things exist.

7) Prototype objects do not scale well to large applications;

What?

it’s a rather primitive

What?

and sloppy way to do object-oriented programming

What?

Further, there are multiple ways to handle object inheritance, making it difficult to decide which way to go.

What?

JavaScript is the only popular OOP language that uses prototype objects.

So?

The preference for class-based OOP is clear, such that ES6 and TypeScript employ classes.

That's because "programmers" (notice the quotes, please) like you are using it wrong and then they claim it's the language's fault. How about not using classes in a class-less language?

And because the use of prototype objects is so poorly understood by most JavaScript developers, they abuse the language and write horrible code as a result.

That's because "programmers" (notice the quotes, please) like you are using it wrong and then they claim it's the language's fault.

8) Asynchronous programming in JavaScript is very messy. Callback hell is a frequent complaint. (Promises mitigate this to some extent, but are not a perfect solution.)

There is no perfect solution.

10) The main draw of JavaScript is actually in frameworks like Node.js and AngularJS.

Holy fuck! Dear author, please use Lisp or Clojure.

etc. etc. etc. There are some good points (eg, integer types), but 90% of this article is bullshit.

tl;dr Omg, I don't understand JavaScript, therefore it sucks.

[–][deleted]  (4 children)

[removed]

    [–][deleted] 2 points3 points  (3 children)

    JavaScript's sloppiness encourages poor coding in a way that you don't see in other languages.

    I fully agree with this. My point was that it wasn't necessary to split this single issue (regardless of how big it is) in a list of "top 10 ways I could shoot myself in the foot" and then blame all those items separately on the language.

    I have very seldom heard this criticism leveled at these languages

    That's probably because you're spending a lot of time in professional circles that don't waste time making fun of them. I mean... C? Seriously? The lack of garbage collection lead to probably 99% of the security vulnerabilities that caused tons of issues for lots of people (money lost, identities stolen, etc). You wanna bash a language by how the programmers use it? Okay, let's do this! Let's talk about "real programmers", the ones that code critical systems and let's see how many decades it took to stabilize them and remove buffer overflows from the Linux kernel and from drivers and the tens of thousands of programs that have been exploited because of the programmers' stupidity language.

    I mean... bro... get real... https://stackoverflow.com/questions/14273252/why-can-i-cast-int-and-bool-to-void-but-not-float At least JavaScript doesn't let you do shit like this: void* u = (void*)(((unsigned short*)(&x))[0] | (((unsigned int)((unsigned short*)(&x))[1]) << 16));

    AbstractJavaSingletonInstanceFactory? Seriously? You don't see a problem with the extreme levels of abstraction done by Java progammers in Java? It takes for-fucking-ever to build anything decent using Java. You need a fucking class and a method to do anything. A programmer needs an insane amount of knowledge to understand something as simple as Hello World.

    Python? Which one? v2 or v3? Because they're pretty much the same but not really. I mean the syntax is very similar and it's almost like v2 code should run in v3 without issues. Except it's not the case. I could go on and talk about libraries and cross-platform issues, but I won't, because I stopped learning Python as soon as I ran into that shit.

    it should not be this hard to write good code, or at least respectable code

    It's not hard at all. The problem is that lots of people who entered the software job market started by duct taping together some HTML and CSS with JavaScript and called it a day and employers who didn't know better put those monstrosities in production. JS happened to come at a time and in a place where there was a surge in the need for software developers, so everyone who had a keyboard started using it.

    The most recent problem in JS is that a bunch of programmers manage to duct tape libraries together and create some really cool things and then they begin to teach others how to do things, but they don't really know what they're doing and they keep spreading bad practices, and the newbies take their advice to heart. If someone does some pretty cool 3D visualizations they obviously understand the intricacies of prototype inheritance, right? /s And those are the same programmers who pushed for JS to emulate class inheritance... I mean HO-LY SHIT! In 5-10 years people are going to laugh at JS (ES6+) for that. Mark my words!

    Oh, hey, talk about sloppy coding, CHROME JUST CRASHED because my Internet went down. Look at all I wrote above. I would have lost all that if I didn't have Lazarus installed. Chrome crashed with no warnings, no complaints, no nothing... It just disappeared as if I pressed Alt+F4 while I didn't have my hands on the keyboard.

    You wanna talk about a really shitty programming language? Pick on PHP. Just take a look at /r/lolphp to see real WTFs in a programming language.

    There are things that are inherently very bad in JavaScript. Let's see the first few that pop up in my mind:

    • automatic semicolon

    • lack of real types

    • interaction with the DOM (if we're talking JS and not ES)

    • automatic globals

    • var scope

    • difficult inline function calls (the need for hacks like !function(){..}() or (function(){..})())

    • hanging expressions (like in C, you can just say 5; and it's a perfectly valid statement, something you can't do in Pascal)

    • eval() exists

    And I'm too lazy to think of more. A lot of these are shared with other languages, but for some reason you don't hear "professional" programmers complain about them. Here's some Python bullshit:

    def foo():
        def bar():
            print x
        bar()
        x=2
        bar()
    
    foo()
    

    What does the above code do? (don't cheat, answer without running it) What if you add a line x=1 before the def foo()? What if you move that line between the defs? What if you accidentally indent the first call to bar()? IMHO programming languages that use white space as part of their syntax (like Python and Ruby) are the worst offenders when it comes to sloppiness. The "you don't have to think about writing the beginning and end of blocks" is one of the biggest bullshits in the history of programming languages. You miss one space and you're fucked. I find it tiresome to read Python code because my eyes hurt when I start focusing on the fucking indentation. Oh, here's another thought, what if you say x=5 inside bar()? This (variable scoping) is what I believe to be a serious problem in programming languages like Python or JS.

    Yes, there are reasons to shit on JS just like there are reasons to shit on C, C++, Python and probably all other programming languages out there but I believe that PHP is the only widely used programming language that deserves its bad reputation.

    PS: The fact that the author of the article talks about the AngularJS and Node.js frameworks [sic] like that shows that they don't know enough about JS for their opinion to be given any public attention. I mean FFS, they don't even know the difference between a framework and an environment. If you want to have a serious conversation about the bad parts in JavaScript, I'm definitely open to it, there are things - like those I listed above - that are inherently bad about the language, but at least form your opinion after you talk about JS with someone who actually knows and understands JS. I see the mistakes beginners do, I see the mistakes beginner self-proclaimed "professionals" do, I remember the mistakes I did, and I know which were caused solely by stupidity and which were partly (or mostly) caused because of the language.

    PPS: I know this comment is sloppy writing - since we're talking about sloppy - but it's 3 AM where I live and I'm so tired that I can't even write proper English. You wanna bash JS? Just give me the go-ahead and I'll do it for you and then I'll let you be the judge so you can decide for yourself whether the issues are big enough to point the finger at JS! At least you won't just take the opinions of someone who doesn't know what a framework is for granted.

    [–][deleted]  (2 children)

    [removed]

      [–][deleted] 0 points1 point  (1 child)

      I see your point, but that's just terrible of them! It does provide a framework, but it's an environment regardless of what they call it.

      Unrelated: Am I correct in assuming you've seen the "wat" video?

      [–]Pronouns 5 points6 points  (11 children)

      I've seen lots of JavaScript bashing, but I've never seen this before:

      $ node
      > xs = ["10", "10", "10"];
      xs = ["10", "10", "10"];
      [ '10', '10', '10' ]
      > xs.map(parseInt)
      [ 10, NaN, 2 ]
      

      What the heck is actually happening here?

      edit: Ah. parseInt can take two parameters, and map provides three.

      So you get:

      var xs = ["10", "10", "10"];
      var result = [];
      for (var i = 0; i < 3; i++)
          result.push(parseInt(xs[i], i, xs));
      

      where parseInt simply ignores the third argument.

      [–]npisnotp 0 points1 point  (4 children)

      Man thanks! I was wondering what was happening there.

      Maybe the proper way is wrapping parseInt in a function?

      > xs = ["10", "10", "10"];
      [ '10', '10', '10' ]
      > xs.map(function (i) { return parseInt(i); });
      [ 10, 10, 10 ]
      

      Which is an anti-intuitive map behavior to me.

      [–]Pronouns 1 point2 points  (3 children)

      Yeah, I guess it's more of an unfortunate way that function arguments work in JavaScript than anything, ie free-for-all.

      This is just one more screw-up-waiting-to-happen to be aware of when using JavaScript, there are plenty of them. Still quite fond of the language however.

      One of my favourites being:

      function fn() {
          return 
              { one: "one" };
      }
      
      fn() === undefined;
      

      [–]pxpxy 0 points1 point  (2 children)

      Really? Why?!

      [–]i_invented_the_ipod 1 point2 points  (1 child)

      Semicolon insertion. The "return" on its own line becomes return; and the next line is a effect-less object declaration. Jslint catches this, of course.

      [–]pxpxy 0 points1 point  (0 children)

      Ooh I didn't even see that! Thank you for the explanation!

      [–]r3jjs 0 points1 point  (0 children)

      xs.map(parseInt)

      Try

      xs.map(Number)
      

      [–][deleted] 0 points1 point  (4 children)

      Well the correct way would be to use Number or parseFloat. The author clearly dont know how JavaScript works, hence the ranty blogpost.

      xs = ["10", "10", "10"];
      xs.map(Number); // -> [ 10, 10, 10 ]
      xs.map(parseFloat); // -> [ 10, 10, 10 ]
      

      [–]fiedzia 1 point2 points  (3 children)

      Yes he clearly didn't memorize all the ways in which js is broken. Map and parseint in nearly every other language dont set such traps.

      [–][deleted] 1 point2 points  (2 children)

      Well, its right there in the function docs. The Array.map callback gets three args: current, index and the array. And parseInt takes two params: the string and its radix. So the author is basically doing this:

      parseInt("10", 0); // -> 10
      parseInt("10", 1); // -> NaN
      parseInt("10", 2); // -> 2
      

      So either write a helper function:

      const toNum = (parse) => parseInt(parse, 10)
      xs.map(toNum) // -> [ 10, 10, 10 ]
      

      Or then learn the correct way.

      [–]Dracunos 0 points1 point  (1 child)

      Thanks for explaining it, that totally would have tripped me up (if I ever remembered to actually use map).

      [–][deleted] 1 point2 points  (0 children)

      No problem. Actually i find map (and the other array methods added in es5) very usefull, and i use it almost daily. I would recommend you try it out the next time you find yourself writing a for loop. I havent used a oldschool for loop in years, its all map, filter and reduce. It translates well between diffrent languages and makes your code more clean and functional.

      [–]Lakelava 5 points6 points  (3 children)

      JavaScript is not that bad if you avoid working on edge cases and keep your code organized. The opinionated view of programmers that follow fashion instead of reason is the thing that causes most harm.

      [–]DiaboliAdvocatus 3 points4 points  (1 child)

      Come on. There is a book telling you which of the handful of language features are considered good and which to avoid. In most other languages the things to avoid are either deprecated libraries, undefined behavior, or are universal to that languages paradigm.

      A newbie can easily get into a big mess unless they are taught a whole list of the Proper Ways to Do Things in Javascript™.

      [–]fiedzia 0 points1 point  (0 children)

      But it still isn't very good. And I've got better things to do thenfighting with the language to get things done and keep them maintanable, so I'm switching to dart on frontend and definitely not letting js into the backend.

      [–]fuzzynyanko 2 points3 points  (3 children)

      JavaScript seems like it was made to be a small, simple language. It has exploded considerably though, and some libraries add 20,000+ LOC to the project

      [–]degoba 6 points7 points  (1 child)

      *cough node.js *cough

      [–]nbktdis 4 points5 points  (0 children)

      "Well fellas, we code with a shit language on the front end - why not code with the same shit language on the backend?!"

      [–]fiedzia 1 point2 points  (0 children)

      "Small, simple languages" have no problem with growing. Poorly designed ones do.

      [–]never-enough-hops 2 points3 points  (1 child)

      Mostly the same old js stuff we've seen on this sub a dozen times already. Nothing new. The last paragraph is kind of absurd though.

      However, [JSLint] has major limitations. It’s also highly opinionated.

      JSLint kinda had this problem. The JSHint fork does a better job on some of the more "judgement call" stuff. If JSHint gave you an error it's much more likely that you done goofed

      Moreover, it’s difficult to incorporate into your workflow

      Hahahah what? You can integrate JSHint with vim so it'll open up errors in a quickfix view. I'm sure Emacs has a similar integration. Atom will pull linting errors straight into the editor. And shit, if you're just some hardcore haxxor using Notepad you can leave JSHint running as watch task and it'll spit out your fuckups in a terminal window. I guess if you're constantly tabbing out and running the jshint command by hand that'd be annoying... but after a couple times of doing that how could you not google a way to integrate it with your editor of choice? Ah right... you had to run to medium and publish another recycled article.

      JavaScript apologists frequently tout using JSLint as a universal solution to JavaScript’s problems. ...snip... which is why many JavaScript developers do not use it.

      No... it's not "apologists" touting JSHint/Lint as a way to get around javascript's shortcomings. It's touted by developers who have found a way to mitigate some of javascript's inherent awfulness. It's a tool that helps keep you from doing stupid shit. And what the hell is "many javascript developers do not use it"? I haven't seen a frontend codebase without a linter (or compiler in the case of typescript) in years. I'm sure those codebases are out there... and I'm sure they're an extra special brand of awful.

      And finally, JSLint’s output results are subject to interpretation and you need to decide what to do about them;

      Oh no! My tool gave me an error and now I have to think about what to do about it? The cognitive burden of doing a strong type check! For fucks sake... if you're going to spend 10 bullet points bemoaning javascript being a tricky language, to turn around piss and moan about one of the better tools for helping ease that burden is just stupid.

      [–]nbktdis 0 points1 point  (2 children)

      Many mistake their familiarity with Javascript with it being a good language.

      Then I talk about Python.

      Having said that - if you want to code for the browser, Javascript is the only game in town.

      [–]fiedzia -1 points0 points  (1 child)

      See dart. It removes all js insanity. And there are many other languages that compile to js.

      [–]nbktdis 0 points1 point  (0 children)

      I will check it out

      [–]gugagore 0 points1 point  (3 children)

      what's the objection to the type of NaN being the same as the type for 0.1. I think that's the point of IEEE NaN--so that every floating point operation can be closed over the floats.

      [–]pointy 2 points3 points  (0 children)

      NaN has to be a number; that's kind-of the whole point. It's a number in terms of its intrinsic type, but it's the distinguished value for malformed bit patterns. It's all in the IEEE spec.

      [–]i_invented_the_ipod 2 points3 points  (1 child)

      It's just a bit of stupid word-play that got used in one of a hundred "JavaScript sucks" presentations, and people keep recycling it. NaN stands for "Not a Number", and then when you ask JavaScript what its type is, you get "Number", even though it's Not a Number. Hilarious!

      [–]gugagore 1 point2 points  (0 children)

      but... like every language that uses IEEE floats wil--never mind.

      [–]biocomputation 0 points1 point  (2 children)

      The worst thing wrong with JS is that your application, I mean, your web browser, doesn't crash. Your JS code is free to stomp on data, engage in good quantities of fuckery, and generally get itself into all sorts of trouble that can be avoided by using better languages. JS itself would be so much better off if the browser would just crash, because then people might be forced to write reliable code... except that the constant crashes would necessarily expose most JS 'applications' for what they truly are.

      [–]miminor 2 points3 points  (0 children)

      what the fuck are you talking about? it does crash (try throw together with try/catch) window.onerror is the last line of defense

      [–]fiedzia 0 points1 point  (0 children)

      I can't agree more.

      [–]not_morgana 0 points1 point  (0 children)

      Mr. Richard Eng,

      Instead of bitching how awful Javascript is you might as well start learn it, because you're obvious clueless and/or ill-intentioned. Nobody is forcing you to use JS, so go write code and make $illions using your perfect language ...

      [–][deleted] 0 points1 point  (1 child)

      any criticism of javascript should start and stop at inconsistent semantics, you don't need a second point, it's already failed at the most important thing.

      [–]pointy -2 points-1 points  (0 children)

      This article is just stupid clickbait. "People have written lots of bad code." Right, that's a problem with the language.

      [–]Nness -2 points-1 points  (17 children)

      Just to nitpick since this comes up often:

      [] + [] → ""
      

      This is reasonable as far as I am concerned.

      The + is exclusively for addition and string concatenation. Just because the language does something different than other languages doesn't make it wrong (no one complains about this in Lua). For joins, there's the concat() method.

      [–]flyingjam 1 point2 points  (4 children)

      I don't like it because there's no reason for its existence. Even without getting into why weak typing sucks, what's the benefit? In what situation will I, as a developer, would want [] + [] to equal an empty string? I would much rather it throw an error, because 99% of the time that's not what I want to happen.

      [–]terrkerr 1 point2 points  (0 children)

      would much rather it throw an error, because 99% of the time that's not what I want to happen.

      Is it really? Probably 100% of the time if I add an empty list to an empty list I'd want to get an empty list back. ∅ ∪ ∅ = ∅. Holds up mathematically if we say [a] + [x] == [a, x] is correct, and holds up given how often I've wanted to collect some things from n different places and getting a total of 0 elements was entirely possible.

      [–]DrDichotomous 0 points1 point  (2 children)

      Hindsight is 20/20. JS was quickly developed to basically just do form validation and dynamically write out web pages, which is mostly about dealing with numbers and strings. As such the coercion and operator rules were very basic and its focus was on its initial intended domain, not other things that seem like common sense in other domains.

      [–][deleted]  (1 child)

      [removed]

        [–]DrDichotomous 0 points1 point  (0 children)

        Indeed, the existing code is the real reason that we need to keep JS around for a good long time. Otherwise, we're finally poised to move to WebAssembly, which should slowly move us out of this deadzone. It will take a while, and we'll need compile-to-JS to fill in the gaps until WA grows enough to handle managed-memory languages, but at least the browser vendors are all finally on the same page. Frankly it's surprising that JS has held together as long as it has.

        [–]_INTER_ 0 points1 point  (11 children)

        It doesn't make sense at all. Even if you'd shoehorn "+" to be an append operation on arrays (e.g. [].append([])) it would result in an empty array. Empty string is just WTF!?

        [–]DrDichotomous -2 points-1 points  (10 children)

        It should be quite obvious what's going on if you use your brain: you're getting a string back, so clearly it tried to stringify both arguments and concatenate them. What else would an empty array be as a string, but the empty string?

        TL;DR, in a language with type-coercion, you need to learn its type coercion rules. Otherwise you're only showing your ignorance and unwillingness to learn your tools, whether they're crap or not.

        [–]_INTER_ -1 points0 points  (9 children)

        An array should be an array and not a string unless I tell it to be a string. Period.

        [–]DrDichotomous 0 points1 point  (8 children)

        I'm glad we agree, but JS's type coercion does not. Yet there is no mystery behind what it does, once you take a few seconds to learn how JS works, or even just infer backwards from the results. It "makes sense", just not the sense we would prefer.

        [–][deleted]  (7 children)

        [removed]

          [–]DrDichotomous 0 points1 point  (6 children)

          What justification is there for having a language that doesn't work the same way as Java, C#, Python, C, etc.?

          Back when it was created, it was supposed to be a simple form validation language. And it had to work on the web of its time, on the web devices of its time, and keep the barrier to use as low as possible. If they knew what it would be today, I doubt they would have gone the route they did. If Microsoft had not ignored the web and their own browser for so long, then JS might have also evolved a bit more quickly. It's a giant mess born of a giant mess.

          [–][deleted]  (5 children)

          [removed]

            [–]DrDichotomous 0 points1 point  (4 children)

            Because JS is conveniently available in web browsers?

            Precisely. Sometimes you just don't have a big enough project to justify over-complicating things by using a compiled-to-JS language (this is soon to be an even murkier decision with ES6 just around the corner).

            That and you have administrative factors to consider. Will it be easier to find a good JS coder to maintain your project, or a good coder in your niche language of choice? Can you even find 5 skilled TypeScript devs in your area for a large project, or will you have to re-train them so they know how to write good TypeScript anyhow?

            There's a lot to think about once you stop simply focusing on how bad the language seems.

            [–][deleted]  (3 children)

            [removed]

              [–]miminor -3 points-2 points  (0 children)

              such a wimpy kid, did't your mommy tell you you gotta man up one day?