Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

This is actually pretty funny. I coded javascript for a solid ~18 years (I stopped about 3 years ago) and the majority of the concerns in this list are from the past 10 years. What I find glaringly absent, which would have been present if this were written in 2013, is the absence of polyfills.

What other things that were JS nightmares in 2013 have largely ceased to exist? (Only to be replaced by this funny list.)

This is my favorite part: "You stop to count how many tools and parsers work on your codebase: TypeScript, esbuild, swc, babel, eslint, prettier, jest, webpack, rollup, terser. You are not sure if you missed any. You are not sure if you want to know. The level of pain is so high you forget about anything else."



Grunt, Gulp, CoffeeScript, IIFE, overridden undefined, with, closures to create private fields, modified prototypes, variables global by default, call-site-this, automatic conversions for comparisons...

Ah yes, over a decade of JS.


Overridden undefined?

Omg, that’s awesome. I think anyone feeling like a corporate mindless drone should sneak that into a code base.

And I thought overriding toString() was naughty.

In my defense, on my personal projects I have started using var instead of let/const, snake_case everything, don’t use semicolons, manage my objects with my own prototypical inheritance, and am fucking around with my own shitty Canvas2D widgets. Turns out ditching the DOM and using a Turing complete language still beats the crap out of wrestling with the DOM even if you have to reinvent things like word wrap and text areas.

Oh! And there’s not a framework in sight.

The funny thing this is, my productivity and error rate have way improved. Prob coincidence but I do actually enjoy it much more.

Take that ChatGPT!

edit: I actually write web assembly by hand too. Binary even. And have my own little shim in wasm to override its type safety, put code in my heap space pure von Neumann style, and have my own program counter so I can jump and goto. Can’t wait to start doing self-mutating code.

I know this sounds like I’m being sarcastic here- I often actually am- but I kid you not my error rate has plummeted and its become a blast to program again.

My internet actually slowed to dialup speeds lately so I’m only going to MDN or Stack Overflow if I really have to as well.

‘Modern javarscript’? Hahahaha.


undefined couldn't be minified. If you assigned it to an undefined variable early on, any minifier could easily convert it to yet another single-character variable name.

undefined became U (for example). An 8-byte or more reduction per reference. What can I say? Size used to matter. (Been doing JS since 1996.)


If you allow it I think most minifiers nowadays use `void 0` for undefined as it’s smaller.

Though I should try this, using a variable alias for undefined and null would maximize minification.


this list feels just a short jump from “we didn’t start the fire”


Inspired by it: We're gonna build a framework

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


I am so glad you shared that. I've never seen it before and it made me laugh so hard I cried.


The only change in lyrics is “it’s been burning us since…”


"It's been burning, since IE was turning"


I kinda miss CoffeeScript, to be honest. I also miss ExtJs.


I have done things with Ext JS that now take me forever with React + MUI. I miss it too.


Aren't there commercial ExtJS-like frameworks built on top of React? Kendo UI commes to mind.


It really depends on what you're missing from ExtJS. Yes, there are some frameworks oriented towards more desktop-like UI components. Some of them even do layout, maybe even non-view stuff (Kendo seems to do at least the former).

But there are other degrees of ExtJS nostalgia:

- Being allowed to do everything in a desktop-like manner, and not having to bother too much with either mobile or more stylized web applications, even in enterprise contexts. No technical issue, no technical solution.

- Doing that in a simple manner. Even contemporary (> v4 or even v3) ExtJS might not be "ExtJS" in this regard, as the framework part got a lot more complex. First with their own weird tooling, nowadays with the worst of both worlds.

- Not having to touch HTML and CSS. Early ExtJS allowed you to do most things with heavily nested JS literal objects. With angular/react/etc. it's all separate syntaxes, most of them with angle brackets.


I'm also a bit pissed that in the past 10 (or more) years we still haven't gotten good established components in the browser that do even half of what ExtJS could do (and still does).

We may have some by 2050 thanks to https://open-ui.org

Browsers did pour billions of dollars and hundreds of thousands of man-hours into a lot of bullshit though :(


CoffeScript is pretty much alive. It even has JSX support now. Although lacks types and tooling.


var that = this


I always favored `self = this`, personally


Careful not to overwrite global self!

Oh the foot guns of `this`


dealing with IE6 nightmares


The IE6 debugger, specifically, which Did Not. Especially when it was a very specific IE6 crash bug that did not occur in any other context. Drawing vml polygons on maps.


error on line 0


I second @golergka about callbacks.

The BIG pain point for me, though, looking at my 10-year-old JS, is that it's all made of "classes" built up by modifying SomeFunction.prototype, which then get wrapped in a self-invoking anonymous function and returned as an object, just so you can call `new SomeFunction()` ... `SomeFunction.actualFunction()` as if SomeFunction were a class. That and also the lack of arrow notation; modifying Function.prototype itself to use .apply() to bind events to scope (or else just an endless abyss of .bind(this) in event callbacks)...


Today I don't even write promises anymore. Using fp-ts and piping data through Task and TaskEither monads feels so much better and easier to write and maintain.


I know what most of those words mean, but I have no idea what they mean in that order. This feels symptomatic of the general state of Javascript, where I've not written any for a year or so and am now wildly out of date.


People often complain about how complex it is, but it’s really just a matter of passing endofunctions through transplainer pipelines so that you can asynchronously hydrate the islands.


Seriously, once you understand the ui as a superposition of entangled complex-valued eigenstates that only collapse into place once an observer visits your page, frontend development becomes so much easier.


Why would you ever even need to pass an endofunction through a transplainer pipeline? There are far more efficient ways to do async island hydration in Elm.


The thing is — I'm actually quite stupid. I don't even understand what a monad is. I just FP because it's a good tool. So, here's an example. I'm building an automatic storyteller on top of GPT-4 — it's a toy project to build the LLM-based functional library. Here's how the code looks, with comments: https://gist.github.com/golergka/3fdc6b9cf9717bd1c0b315925a8...

This is literally 20 lines of code, and it doesn't take that much to learn to read it easily. When I originally implemented LLM-based applications in Python, it would make about 10 times more, and all the components wouldn't be as modular. I can change the functionality of this code in a very drastic way with minimal code changes and with safety of completely statically type checked code.


Thing is: you don't read it easily. It's basically a custom DSL bolted on top of Javascript that hides actual functionality beneath an Everest of abstractions.

That is, it's a yet another library trying to force Haskell/Haskellisms into Javascript and claiming with no proof other than emotions that it's so much better and more readable than something.

Here's an actual readable version of that:

    try{
      return getTurnPromptMessages(state, action)
        .map(mkCCRequestFromMessages)
        .map(addSchemaToRequest)
        .map(handleChatCompletion)
        .map(extractFirstCompletionChoice)
        .map(extractChatCompletionMessage)
        .map(decodeSchema)
        .map(detectLocation);
    } catch (e) {
      mkMessageError(e);
    }
It can be further simplified. For example, you don't need two separate functions to extract the first chat completion message etc.

This version:

- uses existing language constructs

- can be immediately understood even by the most junior devs

- is likely to be 1000 times faster

- does not rely on an external dependency that currently has 143 issues and every two weeks releases a new version adding dozens of new methods to things

Note: one thing I do wish Javascript adopted is pipes: https://github.com/tc39/proposal-pipeline-operator


Your version doesn't work.

* all but the first results are not arrays, so the `.map` function doesn't apply

* doesn't handle async operations

* catches ALL exceptions here, whereas my code only handles statically typed and well-defined errors

* doesn't include the GPT-generated message and messages from the first steps in the error

* doesn't include retry functionality

I appreciate this argument and time you've taken to read my code and write this counter-argument. Please don't mistake my direct code for animosity, I clearly see that you're a smart person even though I think you're wrong about this.

Also, the fp-ts doesn't add any runtime performance overhead here. It's a couple of extra function calls for a call that has an async operation that likely takes 30 seconds (GPT-4 is slow). Obviously, if I was writing code that runs thousands of times per second, I would not use FP.


> Your version doesn't work.

It does.

It was also somewhat tongue-in-cheek, and a five-second copy-paste of your code.

> all but the first results are not arrays, so the `.map` function doesn't apply

Unless you return arrays from all functions.

Not that different from wrapping every result into seventeen layers of functional abstractions. What do you think flow or flatMapEither does?

> doesn't include the GPT-generated message and messages from the first steps in the error

Of course it does. That's what the catch is for.

Or you could use an additional map if you want.

> Also, the fp-ts doesn't add any runtime performance overhead here. It's a couple of extra function calls

Of course it adds runtime performance overhead. Any additional function call adds a performance overhead. And in your case it's dozens of functions wrapping trivial functionality.

> Obviously, if I was writing code that runs thousands of times per second, I would not use FP.

Then why use it here? If the alternative is more readable, more traceable, has better stack traces for errors, doesn't require an unstable ever changing dependency...


> Unless you return arrays from all functions.

But that's not... what they actually do?

> Not that different from wrapping every result into seventeen layers of functional abstractions. What do you think flow or flatMapEither does?

It changes what functions return without having to adapt them to particular use-case.

> Of course it does. That's what the catch is for.

To achieve that, the catch has to assume that the functions throw exceptions with particular data. This cannot be enforced with type system, and once again, tied implementation of these functions to this particular context where they're used.

> Of course it adds runtime performance overhead. Any additional function call adds a performance overhead.

The function call overhead is a couple of dozens nanoseconds at best. And we're talking about a remote call that takes 30 seconds to complete and costs $0,05 per OpenAI's API.

The overhead you're talking about is 0,0000001% in time and I think a few orders less in cost.

> If the alternative is more readable

It's not. An alternative that would actually have all the same functionality would be 4 times as long and more importantly, much more complex to change in a meaningful way.

> more traceable, has better stack traces for errors

But that's the point: we don't need stack traces. We don't need exceptions for errors that we know how to handle.

That's like complaining that a GC-based language doesn't have a tool like valgrind to handle error allocation and deallocation issues.

> doesn't require an unstable ever changing dependency...

I've never had a breaking change from fp-ts and don't expect it to ever happen because of the nature of the library.


Really? I feel like Javascript has been more or less the same since we got `class` keyword. People have been using “FP” words like monad or Either in Javascript for more than 10 years. They weren’t mainstream then and they aren’t mainstream now even if you see them written in an HN thread.


Supporting ie6, ie7, and ie8 separately while developing on firefox just so we could use firebug.


I'm so glad Internet Explorer/Edge/Trident is Officially Over. If you told me in 2010 that in 10 years the worst browser I'd have to support was Safari/Webkit... I'd be overjoyed.


One thing (only thing?) I honestly miss about IE5.5-8 is how amenable the engine was to polyfilling. It wasn't fast, but you could do almost anything with the right polyfill technique.

No sessionStorage? Use window.name. No (then-) modern CSS? Use CSS3PIE [0]. IE doesn't support the transform CSS property? Use an *.htc behavior to convert the transform to a matrix filter.

It was madness, and it was beautiful in a Cthulhu kind of way.

[0] http://css3pie.com/


I was on the "fuck ie6" train. I had to write some support for ie6 in like 2015, I almost quit the job.


Replacing headers with a little Flash applet so that you can use whatever fonts you like, rather than being limited to whatever the user had installed.


Callback hell, and a general lack of types.

I have has a misfortune of spending today writing a test assignment for a company that still uses vanilla JS, without promises or declaration files. Felt right back in 2012 when I first tried node. Worked around the requirement of using JS by utilising JSDoc, but still — it was much worse than I remembered.


For future reference if you ever need to do it again, @callback is roughly equivalent to @typedef but for defining function types, and @template is generic type params for both. It’s not a good TS replacement whatever anyone might tell you, but it’s a reasonable approximation of what you might need in a pinch.


Prototype.js monkey patching every prototype it could get its mitts on


are polyfills solved just with core-js ( https://vived.io/fascinating-story-of-core-js-frontend-weekl...), or is it because people don't support as many different browser engines these days?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: