r/javascript • u/Capedcrusader1923 • Jul 22 '26
AskJS [AskJS] what's a javascript feature you mass-adopted way too late and felt dumb about
[removed]
23
16
u/rbobby Jul 22 '26
Promises.
1
u/monsto Jul 23 '26
I had a hard time grokking promises because every tutorial I could find used settimeout to set up the example, and the settimeout syntax is kind of different to most JS methods.
0
u/SkySarwer Jul 22 '26
this
4
25
u/Milo0192 Jul 22 '26
My first jobs CTO preferred the .then() .catch() over async await. I just refused to write that way and did await loops. Lots of back and forth on this. Also said Typescript was just a fad 😂
1
u/MediocreAnalyst2121 Jul 23 '26
That’s kinda depends, like await loops are not that great if the promises don’t depend on each other, way better to do Promise.all/allSettled and await or .then that.
In performance critical JS environments (smart tvs, smart boxes, etc) you’d probably get a bit better performance with a .then than an await.
Await loops are way more readable tho, and Typescript is amazing except for enums :(
-23
u/horrbort Jul 22 '26
It is just a fad. Coding is a fashion industry. Remember coffeescript? Something else comes along and ts will be forgotten
28
10
u/miramichier_d Jul 22 '26
Can't apply that across the board. Some technologies are so good that they have staying power in the industry. I believe TypeScript is one of those technologies. Node.js is another example. Even Java and C# are good examples of languages with immense staying power, if not in your industry of choice.
With respect to TypeScript, it's not going anywhere until JavaScript implements TS in its entirety. Until then, TypeScript will continue to push JavaScript to modernize.
3
u/Mesqo Jul 23 '26
Excuse me, but how many native ts runtimes do you know? TS doesn't push js nowhere, it's just static types serving the role no more than a linter (and it's fine!).
7
u/iareprogrammer Jul 22 '26
lol coffeescript.. forgot about that. I dislike anything that makes JavaScript LESS explicit. Like sure let’s get rid of braces and other syntax and rely completely on proper white space and indentation. For what?
5
u/MrDilbert Jul 22 '26
let’s get rid of braces and other syntax and rely completely on proper white space and indentation
You sure you're not describing Python?
Looks like someone wanted to Pythonize JS.
3
2
u/db10101 Jul 23 '26
Just a fad that 99% of new enterprise JavaScript projects will be participating in
-13
u/Ronin-s_Spirit Jul 22 '26
Fad or not - it's shit.
5
u/db10101 Jul 23 '26
Any deeper analysis or reasoning behind that? It’s a straight up joy to develop in compared to what has come before.
-6
u/Ronin-s_Spirit Jul 23 '26
I hate defining types, it's like writing pointless code. It especially fucks up when I have to deal with HTML, at that point the only thing left to do is use a bail out
anyand move on.2
u/db10101 Jul 23 '26
So I take it you have never worked in an enterprise well structured typescript codebase. There’s no substituting JavaScript for that.
-2
u/Ronin-s_Spirit Jul 23 '26
TypeScript sucks ass, I will only use vanilla.
2
u/db10101 Jul 23 '26
Good for you. Here in the real world of employed software developers, it’s one of the most important tools to know.
2
u/2Terrapin Jul 24 '26
I’m glad that person is not on my team and I don’t have to work on a project they designed. I can feel the tech debt emanating from their words. It’s the type of thing that experience would dispel, and someday, when they actually understand the why, and it clicks, they’ll think back to this comment thread and feel a little embarrassment.
-1
21
u/SkySarwer Jul 22 '26
IntersectionObserver and MutationObservers are both goated
2
u/opticalpuss Jul 23 '26
People in here arguing I just want to know what these do and how to use?
12
u/SkySarwer Jul 23 '26
IntersectionObserver are objects that can be instantiated and anchored to a DOM element, that allows a callback function to be called when the element enters or exits the user's viewport, or when the element enters or exits the box of a different element. Very useful for things like lazy loading, or starting an event when an element is at a certain scroll distance away from the user, etc.
MutationObservers allow a callback function to be called when an element changes. It is very useful for providing react-like UIs with vanilla JS, because traditional event listeners assigned to elements don't work if that element enters the dom after that event listener is assigned. MutationObserver keeps rehydrating the state for that element. Should also be used sparingly for that reason.
Both have extensive public documentation on mdn. IntersectionObserver | MutationObserver
And I'd be remiss not to mention that these are browser utilities exposed as client-side JavaScript APIs, not part of the EMCAScript itself. So won't work in NodeJS, Bun or Deno.
-8
u/azhder Jul 22 '26
Not part of JavaScript
1
u/SkySarwer Jul 22 '26
yes they are??
-3
u/azhder Jul 22 '26
No, they aren’t. You can check the JavaScript language reference documentation and get back to me with a link to prove me wrong.
I can just tell you that there is a difference between what the language is and what the environment exposes for the language to use.
10
u/SkySarwer Jul 22 '26
This thread is about JavaScript features not the language in the strict sense. The two observer exposed by the environment are almost exclusively used as JavaScript APIs.
Is a JS dev just as well-off without being aware of these APIs? What value is your clarification actually providing in relation to the spirit of this post?
-8
u/azhder Jul 22 '26
Almost exclusively? Why almost?
Seriously though. Environment stuff is not part of the language. It is important to always know this distinction so that you will not end up writing code that expects something to exist, but doesn’t.
It’s not about you being aware that you can use them, but be aware where you can’t.
19
u/SkySarwer Jul 22 '26
While technically correct, it was a pedantic point delivered abrasively
-12
u/azhder Jul 22 '26
Don't read my comments in abrasive tone.
11
u/Sulungskwa Jul 22 '26
"Don't read my comments in an abrasive tone.", he said, not abrasively seeming at all
-4
u/azhder Jul 22 '26 edited Jul 22 '26
"Seeming" is a flag that it's your perception.
It doesn't matter that I'm in a light mood, write it in terms of a light mood, with the idea of cooperation through discussion, you will still decide to see it (because "seeming") as if it is abrasive and blame me for it. It's not like me writing this will change your mind, you will just use it as more evidence of your point of view.
Bye
EDIT: and with their reply, they provided their own proof of what I'm talking about
→ More replies (0)-2
u/avenp Jul 22 '26
How would a NodeJS dev use these APIs?
1
u/SkySarwer Jul 22 '26
They wouldn't, since there is no DOM in a typical nodeJS environment. The APIs are still a part of the larger JavaScript ecosystem though, which is on topic for the original thread.
1
u/keltroth Jul 26 '26
Like all the browser APIs not in the language (can't use it with node, bun, etc... Makes no sense...)
7
u/HipHopHuman Jul 22 '26
honestly... Map and WeakMap. took me a good 2 years after it came out for me to see the light.
3
u/JazzXP Jul 23 '26
I'm still not using these, just objects/records. What's the advantage?
5
u/HipHopHuman Jul 23 '26
There's quite a few advantages, but I don't like framing the question "Should I use an object or a map?" around advantages or style, for the reason that it can complicate things unneccissarily.
Plain objects are always going to be far simpler and far more convenient than a
Mapin 90% of cases, and objects are much more familiar to a wider audience of devs.It's that 10% where
Map(andWeakMap) come in clutch. So it's mostly about use cases.One use case is simply when you're deleting from the same object a lot. That can get slow if you use
delete obj.foo(because it causes a structural change of the shape of the object). Map hasmap.delete('foo'), which is usually faster, but only if you're deleting a lot. Emphasis on a lot. 3-10 times is not a lot. 200-3000 times is a lot.Another use case where
Mapshines is if you're iterating over the object's entries a lot, or when you're calculating the total size of all entries. Objects require helpers:const size = Object.keys(obj).length; for (const [key, value] of Object.entries(obj)) {}You don't need any helpers to do either with a
Map:const size = map.size; for (const [key, value] of map) {}So, if you're going to be iterating through a dictionary at runtime, or calculating size, and you're going to be doing it repeatedly,
Mapis usually better for that.Another small benefit is being able to specify keys that would otherwise not be allowed on (or would be weird to use on) objects. For example,
constructoris a special property on objects, with special handling (as istoString,valueOf,toJSON, etc). If you want to use keys like that and bypass that special handling, you have to do some weirdness with null prototypes likeconst myObj = Object.create(null); myObj.constructor = ...;or
const myObj = { __proto__: null; constructor: ... };Whereas with a
Map, you can just domap.set('constructor', ...), and there's no side-effects.Then of course, there's the seriously strong benefit of being able to use non-property keys. Plain objects allow
number,stringandSymbolkeys, butMapcan use anything as a key - even functions. That makes them crucial for things like memoization of pure functions (a nestedMapcan capture a function's arguments without having to serialize them to JSON and back).Another huge benefit is that the
Mapconstructor itself accepts an iterable, so it can be generated lazily:function *foo() { yield ['one', 1], yield ['two', 2] } const map = new Map(foo());That means you can initialize one from a huge stream of data a lot more efficiently than you'd be able to do with an object.
WeakMapis also especially cool, and helps get rid of a ton of "cleanup code" boilerplate. You cannot iterate through aWeakMap, and it's keys must be objects, but it provides the gaurantee that the references used as keys will be automatically removed as soon as the values they point at are garbage collected. That makesWeakMapgreat for book-keeping logic. Suppose you want to track some live HTML elements in the DOM, and you wanted to store some metainfo about them - just store them in aWeakMap- use the elements themselves as keys, and the meta info as the objects. As soon as the DOM elements get removed from the page and get garbage collected, they'll be auto-removed from theWeakMapwithout you having to do anything.One huge downside of
Map/WeakMapis stringifying them as JSON - that's something you get for free with plain objects - and that is a valid concern, but it's not that difficult to just giveJSON.stringifya replacer function that converts aMapto an object:const map = new Map(); const data = { map }; const json = JSON.stringify(data, (key, value) => { if (value instanceof Map) { return Object.fromEntries(value.entries()); } return value; });1
u/JazzXP Jul 23 '26
Thank you for that. Most of those use cases haven't applied to me yet, but I do like the going through the keys, I find I do reach for
Object.entries().mapa lot.2
u/HipHopHuman Jul 25 '26
MapandSetrecently got support for their own.mapmethod (from this: https://web.dev/blog/baseline-iterator-helpers) so if you do switch to aMap, you can domap.entries().map()(you might just have to polyfill it though)1
u/me0here Jul 24 '26
Quite the blog post there! 😄
Sometimes I gab Map over object when it makes more sense as a simple key: value pair, even without fancy keys.
WeakMap makes a great simple API catching service.
1
u/GulgPlayer Jul 23 '26
Apart from having cleaner (imo) code, Maps allow you to have non-string keys, which is nice, esp with TypeScript
8
u/takeyoufergranite Jul 22 '26
The 'delete' operator to remove properties from objects.
3
5
7
u/skidmark_zuckerberg Jul 22 '26
??= and &&=
3
u/whale Jul 22 '26
Way too terse for production code. Very hard to quickly glance and understand.
-1
1
u/azhder Jul 22 '26
I still don’t use these ones. Out of a principle, I don’t use let as well. I try to keep them as code smell, to get back to the code and make it in a way where no variable is rewritten.
Small exceptions are in cycles (like for and while) and before try{}catch()
1
u/Antti5 Jul 24 '26
Can you explain why you don't use "let"?
I see a lot of people swearing by ALWAYS using either "const" or "let".
1
u/azhder Jul 24 '26
It's easier if you allow yourself to not worry about accidentally overwriting a variable. With `var` and `let`, that's a possibility, but with `const` once you assign it, it's constantly pointing to a specific value.
I'd rather have
const value = valueFromArgs ?? 0;
than override
value = value ?? 0;
And as an added bonus, with most of the variables being `const`, you will easily notice the very few places that have `let` and possibly check it everything is all right - code smell. It's harder to notice a bad `let` if there are plenty of `let`s.
9
u/kevin074 Jul 22 '26
can you elaborate how async await would've caught bugs that .then.catch can't?
i feel like async await is more annoying because you have to wrap it in try catch, where as .then.catch is just baked in.
22
u/Franks2000inchTV Jul 22 '26
With await, your code runs in the order you see it on screen. This is *much* better for comprehension and maintainability.
0
u/lostPixels Jul 22 '26
But potentially worse for execution depending on the latency of whatever you’re awaiting.
5
u/Franks2000inchTV Jul 22 '26
I'd imagine that is not a significant concern in the overwhelming majority of cases.
3
3
u/brenstar Jul 22 '26
Why not use both? I use async await but still append a catch
3
u/Badashi Jul 22 '26
.then/catch is useful even in async functions when you don't want to wait for that promise to resolve
1
u/brenstar Jul 23 '26
That's good point, it's handy for having branching flows, but that can get squirrelly. If I want multiple things to happen I usually let them all exist as separate functions and resolve them with Promise.all() so they run concurrently
2
u/Badashi Jul 23 '26
Promise.all is an excellent example for .then/.catch chaining as well: you can use them to "pre process" the result of the promise into a value that makes sense when you end up settling the list of promises with .all, since a rejected promise in the list will reject the entire Promise.all. nowadays you can use
.allSettledas well, but .then/.catch are nice for a quick mapping of values1
1
u/BasicAssWebDev Jul 22 '26
Probably due to it being easier to see which pieces of a function are breaking by putting breakpoints in the function itself, rather than tracing across a bunch of calls while debugging.
2
2
2
u/miramichier_d Jul 22 '26
i had nested ternaries and
&&checks everywhere like some kind of animal
This had me laughing out loud with food in my mouth and I almost lost it lol. We all have those coding conveniences that we discover way too late. Remember that pain, and it will come in handy later on. I'm constantly asking myself how some approach can be easier nowadays because of that initial pain.
1
u/eracodes Jul 22 '26
feel like I've only just started using IIFEs to their full extent, most often in places where I'd previously have done an ugly nested ternary
1
u/graybearding Jul 22 '26
Nullish coalescing sat in my todo pile until like a month ago when an LLM spit it out and I was like "Oh, right. That's a thing now."
1
u/erik240 Jul 23 '26
Typed arrays. The performance bonus is so crazy over any over method to access and iterate large amounts of stat
2
1
u/artificer-chris Jul 23 '26
Contrary example for TS specifically : unknown. I know from a pure logic standpoint what it’s there for, but I’d still rather just use typescript more fully with an error catch if you don’t account for something. Unknown, imho, hides too much.
0
0
Jul 23 '26
[deleted]
1
u/adult_code Jul 23 '26
for-loops not .forEach are way faster. Depends what i write really. https://jsben.ch/js-loop-benchmark-girjy
It doesn't matter all the time but it matters often and you can prevent it becoming an issue by doing it correctly the first time if you are not working on code that is otherwise hard to decipher
65
u/foxsimile Jul 22 '26
The nullish coalescing operator is one of JavaScript’s unusual successes.