Hacker News new | ask | show | jobs
by wereHamster 1848 days ago
There is existing code out there which relies on negative indexes to return undefined. Or relies on being able to assign items to negative indexes and then retrieve them, this is perfectly valid code: `a=[];a[-1]=42;console.log('the answer is',a[-1])`. The web tries really hard to be backwards compatible and not break existing code.
2 comments

Maybe we should re utilize the "use strict"; type of metadata. Something like "use es2021" to enable negative indexes etc.
TC39 explicitly rejected this sort of approach a few years ago, because of the unpleasant way it would fork the web. They _did_ automatically clean up some behavior in a module context when you knew you were using a modern JS engine, but they kept that to a minimum.

Unfortunately, I couldn't find any links to articles written at the time about this, but they definitely did consider "use" options or script type="es2021" kinds of options.

I can see where they're coming from; backwards compatibility is often a hard problem, and this is no exception. But the downside of this approach is that we'll be living with these sort of backward-compatible hacks for decades to come :-/

Imagine learning JS in 5 years: "you can index arrays with subscripts, but actually, if you want to get negative indexes you need to use .at()"

vs.

"Always add 'use es2021'; at the top of your scripts. You can index arrays with subscripts."

I'm hardly a huge Perl fan, but their approach made a lot more sense IMHO and is a good trade-off between making sure existing code works, and not complicating the language for future use. The "fork" (which seems a bit hyperbolic to me) is a very minor short-term pain at best for significant long-term gains.

I don't know of any other mainstream language that's so conservative as JavaScript in never breaking anything, even optionally with flags.

Besides, compatibility is important but not holy. Some programs probably also rely on "[9] * 2" resulting in Number 18, but we really ought to fix that (with or without flag) IMHO because these sort of gotchas result in people writing bugs every single day where it works for an array length of 1 and then it has 2 values and you get NaN. The pain of breaking backwards compatibility is minor compared to the pain of new bugs being created every single day.

Golden opportunities are being missed here, and it's a shame.

I see two scenarios for ES2042 (possibly both).

0. It will end up completely unnoticed, because everyone is using any language you like and compiles to web assembly, which is the defacto standard for more than a decade.

1. It's like a new C++, because of the many TC39 stage 3 proposals that has been added over the years without the possibility to ever fix the language in order to not fork the web.

I expect what we’ll end up with is languages like TS supporting a flag to convert all/most index lookups into .at() notation. Or maybe it’ll just be an eslint flag.

I absolutely agree that some metadata at the top of a module enabling behavior like this would be ideal.

IIRC Google actually experimented with the idea of an even stricter mode in V8 at some point but dropped it when it didn't materialize the perf gains they were hoping for.

From a spec perspective, ES6 modules were a good milestone to "flip the switch" over to strict mode by default, but even with that being a fairly successful strategy (IMHO), it still left some nasty corner cases around the language (namely, there are now two distinct top level grammars, which led to the whole .mjs bikeshedding rabbit hole)

I've been thinking this for ages.

We need more special contextual comments to change a file or scope to behave better so we can move forward and scrape away all the bad legacy of JS.

> We need more special contextual comments to change a file or scope to behave better so we can move forward and scrape away all the bad legacy of JS.

I don’t think making the JS world into even more of a “set of subtly different languages that look mostly similar” is necessarily a solution so much as an extra problem.

How about deprecating that for a few years then? Doesn't seem good to keep the behavior, given that it will also be confusing in the future.

But perhaps we just don't know enough, and they will add the `at`, and at some point actually do bind `arr[index]` to use the implementation of that function?

There's a large body of existing code out there, some of which might rely on the current behavior but never be updated. I doubt any length of deprecation period would solve this issue.

Instead, adding .at() allows having the new feature now, and in a way that's possible to polyfill for backwards compatibility.

The web as a platform is the most elaborate and epic showcase at not breaking backwards compatibility in the entire history of computing.

In the face of disasters like Python 2->3 and Apple M1 macs no longer being able to play Starcraft Remastered, the web is an aspirational beacon.

Let’s keep it going.

Isn't Windows even more epic?
Windows is very epic, but they did break compatibility a few times: the new driver model since Windows 7 (?) for example.

The Web probably has a longer history of not breaking things, but also has a smaller feature set to keep track of than Windows.

All in all, very hard to compare. But both undoubtedly epic.

The new driver model is Vista-era, I think.
For all the (often deserved) hate Windows gets, in particular the user space API’s, I still find the chaos incredibly exciting and an invitation to hack together all sorts of strange things in strange manners. I’m sometimes surprised by the levels of backwards compatibility and the “obsolete” technologies that still work fine.
You might well be right! Would be fun to see them go head-to-head over the title.
The success of Windows to maintain backwards comparability is probably some of the inspiration for the people working on JS. Windows has demonstrated that it's possible to maintain backwards compatibility for decades.

It's not easy, and it certainly leads to annoying platform quirks, but it is possible.

How would you deprecate it? There's tons of browsers and JS runtimes out there and they all adopt features at different speeds. Undoubtedly some browsers would never adopt the new feature, which means websites will simply break, and the web will become even more fragmented than it already is.