I think a lot about code readability a lot. I agree with most of this except the names part and shorthand constructs. Especially for the latter, it's unfair to make a comparison with the wrong operator. The example in general is a bit weird. I think a better one is `if (myObj !== null) myObj = someOtherObj`. A very common pattern for which js now has a nullish coalescing assignment you can use insteal (`myObject ??= somOtherObj`) or there's also ||=. These sacrifice some readability upfront due to them being "uncommon" operators and the code might be harder to read for someone whose never seen it, but is so much easier to read once you get used to it. There is of course, always a trade off. Using a lot of .? to access properties can be code smell, but also sometimes very helpful, as the alternative would expand into a lot of code.
Regarding names, I think the suggestions are a bit in conflict, as often to avoid variable shadowing you have to do stuff like name things node, _node, node2. I try to have distinct names, but I'd rather the shadowing in those cases where it's hard. As for i, and j. I don't like them, but they're such conventions it's hard to avoid them. I always try to use them only once, and assign the variable I need: `item = obj[i][j]` if possible.
I'm glad the writer has actually tried Tailwind and I respect it's not really their thing, but I've got to hard disagree with the Builder vs Crafter/specialist look on it. Tailwind will only just barely save you from not knowing CSS, it's still fundamental to understand it. Also I would consider myself very well versed in CSS, but while my handcrafted css works, it cannot compare in maintainability to its tailwind equivalent. CSS inevitably becomes a spaghetti soup of states after a while. I switched an entire component library to tailwind + tailwind-merge and everything was much cleaner and easier to understand. So much so I could not believe it.
Right, but sometimes that's just not possible, what then? The only option is to abstract the check into a function which just moves the problem. Or to use a third party library to do exactly what optional chaining does. When I see this argument I just think why should I have to suffer because other people don't know best practices and will produce bad code regardless of whether this exists or not?
I would argue it makes a bad thing easier to read so you can actually tell what's being checked. It's already an easy thing to do, leaving things as they are is not deterring anyone, except it reads horribly. I'm not arguing too many aren't code smell, but what about when it's needed?
The object check syntax proposed on the other hand, imo, does not make things clearer and is of little benefit.
Also regarding callbacks, I meant you can avoid callback hell without using promises. Promises were not technically needed to solve that problem even though they're talked about as a solution to it, you can have promise hells too (and they are exactly what most beginners do with promises). But if used right, the solution is much easier to read and understand. That's how I see optional chaining.
I was scrolling through this and I was like, where is optional chaining? Then when he gets to it, he's a bit against it because it's easy to write bad code. What? People still do nested checks like this all the time! It's not changing anything beyond making them more readable and I think more obvious when you think something might not exist (e.g. `some.very?.nested?.property` vs `some.very.nested?.property`). Sometimes it's not so much the nesting that makes it unreadable either, but that you're checking multiple objects, imagine writing `some.nested?.property && other.nested?.property`.
It's like saying promises shouldn't have been added because you can still write bad code with them and create nested promise hells ( I sure did when I first learned them). Isn't it better to say, no, best practice is to add ? only where you actually need them. The solutions he cites are not really solutions, they're just abstracting the problem away which most of as already do, but then the abstraction becomes hard to read because those checks have to be somewhere.
Worse I think is the comparing objects by value idea. I think it would be way too easy for beginners to reach for that solution. There are often better work arounds, it's quite rare imo to need to do a deep nested check of two objects that could be very different (i.e. contain different properties). Plus it's not like using a helper function is that verbose and a custom one can be really fast (if both objects contain the same properties, creating a function that "manually" checks for them all is blazing fast), same thing with deep clones.
Things I would really like, from most to least: optional chaining obviously, realms, pipeline operator, optional type checking, and enums (you can sort of fake them though, hence why they're last)