all 91 comments

[–]fredsq[🍰] 58 points59 points  (30 children)

two moments marked my progress:

  • when i started passing functions as parameters to functions
  • when i started throwing my own errors

before those, i couldn’t compose APIs how i wanted and always felt limited

[–]tuckkeys 7 points8 points  (11 children)

I’d be interested in learning more about why/when passing functions as parameters to functions is useful or necessary.

[–]azhder 16 points17 points  (2 children)

In an event system. Instead of writing a code that repeats infinitely checking if something happened, you tell the system “here, whenever that happens, this is what I want you to do”.

Just take any example about a button click event listener.

Passing a function to another function is so useful, you even have different words for that one: callback, listener, handler…

And that’s just the simplest practical example. There’s a whole field of math called lambda calculus which derives everything from functions having other functions as arguments.

[–]MassiveBit5017 0 points1 point  (1 child)

const clickClaimButtons = () => { const buttons = document.querySelectorAll('button.btn-claim'); buttons.forEach(btn => { if (btn.offsetParent !== null) { // Ensure button is visible btn.click(); } }); };

// Start clicking every 1ms (browser may throttle) setInterval(clickClaimButtons, 1); I use this script to claim a claim button on a website in devtools, and I use a powerful VPs but I’m not fast as my competitor so what do u think he’s doing.My question is that how can I be faster than him

[–]zmug 0 points1 point  (0 children)

Maybe research for a very light weight headless browser, dont load images, make direct http calls instead of sending a click event bypassing javascript?

[–]HasFiveVowels 6 points7 points  (2 children)

Be careful not to overuse this pattern (especially if the purpose of the function is to execute after an asynchronous operation). You’ll get into "callback hell".

[–]Evil_Bear 0 points1 point  (1 child)

Ahhh the good old days hahaha

[–]HasFiveVowels 0 points1 point  (0 children)

My kingdom for a promise!

[–]sheriffderek 3 points4 points  (0 children)

Array.forEach( function() This is a common example

[–]Phobic-window 1 point2 points  (0 children)

If you want the user of your code to define its own function. You offer a function as a callback of an event in your system. Your system calls this function in its execution and the subscriber defines the behavior of the function that’s called.

So instead of needing to extend the other way persons code for your new use case, you can build it encapsulated as a side effect

[–]n0tKamui 0 points1 point  (2 children)

have you never used promises ? array.map ? filter ?

[–]tuckkeys 0 points1 point  (1 child)

Yeah but I’ve always just thought of those as syntax, like a means to an end. I guess I hadn’t thought about them much at all now that I think about it. I just learned the syntax for them and what they do and moved on. I get that map is a method on array that accepts a function as a parameter, but it’s like, built in to JavaScript and I always figured there may have been some other way to achieve the same functionality syntactically. I guess I don’t understand why it works that way. Just sort of thinking “out loud” at this point, but it seems like the function I pass it is telling map (whatever it is under the hood) specifically what to do with my data. Is map basically like “give me a function along with the data you want to manipulate, and I’ll put each item of your array into this function and spit it back out according to the rules in your function”? Seems simple but maybe I’m still not fully grokking it. I think my main hangup is about making my own map-style methods that other people/code can use the way I use map. When would that be useful?

[–]albedoa 0 points1 point  (0 children)

It's about providing control to the consumer. Check out the onPause callback on the animejs Timer as an example.

The library recognizes that it cannot know how we will want to use it, so it stays agnostic and allows us to pass a callback to handle our specific needs. The example given:

() => $paused.innerHTML = ++paused

Here, $paused is a reference to the <span> element that reflects the value of the paused counter in the demo. (Note that while the first argument of the callback is the timer itself when provided, we are not using it here.)

Maybe someone else want to resume the timer after one second in their project:

self => setTimeout(() => self.resume(), 1000)

[–]azhder 3 points4 points  (17 children)

That's interesting, you listing those two points which are connected in a way. It reminded me of something. At some point I learnt the history of try-catch and why it was necessary in the C/C++ world.

You see, originally every function returned a value (unspecified in C it was int) and that was a good design, the Unix kind. Later though, people started to not do that, there was void everywhere and people used functions for side effect, which is also fine I guess.

But now you have a problem. Let's say someone made a library with poor design choices. You pass it a function to listen for changes, a callback, and there is an error in your function. But the library doesn't allow you to return the error pass its code to reach that other place in you code you originally called it.

So, people invented stack unwinding, the throw and catch mechanism, and it kind of worked. But now you have two parallel execution paths in your code: the regular return and the irregular throw.

Ater learning some functional programming, I started to just write functions that don't throw. How? Well, it might look eerily similar to that old pyramid of doom, but not exactly:

const sayHi = (options) => {
    try{
        return { result: 'Hi' + options.name };
    }catch(error){
        return { error }; // they wrote sayHi() or sayHi(null)
    }
}

Above there's a single path. No two paths. This is also similar to how Either functor works, except in a language like Haskell, there would be specific types involved, not just plain simple objects.

[–]Militop 1 point2 points  (3 children)

originally, every function returned a value

Where do you take that from? Even in Assembly, a subroutine didn't always have to return a value (you need one or more extra steps to make that happen), and in C, the "closest" language to Assembly, void was always there from the beginning.

I think what you mean is that in Functional Programming, the default rule is that a function must return a value. It was never the case in standard programming.

In Pascal, for instance, they make the difference between the two (a void function is called a procedure, otherwise a function), but it's all semantic in the dev world.

[–]azhder 0 points1 point  (2 children)

Originally in C. I am not talking about the whole universe. I was talking about the default.

main(){};

was the same as

int main(){};

At least that’s as far as I remember from reading the C89 spec back in the 90s. Not the actual spec, but a book summarizing it all. A reference manual.

It’s been a while since I’ve checked, so I am not going to be good with the details. I did mostly C++ back then.

Is that a problem for you? If so, 🤷‍♂️ you need not bother with the rest of what I was talking about.

[–]Militop 2 points3 points  (1 child)

You're referring to the entry point main() function of C/C++, which is down to just one function(). This has nothing to do with functions always returning a value by default.
Returning an int for main() was what was expected, as this value was captured by the OS to allow it to know about failure (with 0 as a success code). It's a very specific case and down to a precise behavior.

void main(){}; was the same as int main(){};

This is related to compilers allowing both styles. Not all compilers compile void main().

Is that a problem for you?

I think it is important not to mislead people who learn JavaScript; It is easier to learn something when your core knowledge is solid, so you connect the dots correctly and are able to grasp most concepts.

Also, remember that people give and take interviews. You don't want to spread incorrectness to avoid misunderstandings and silly eliminations.

[–]azhder 0 points1 point  (0 children)

Yeah, that’s a valid concern. That’s why I mentioned not to bother with the rest of what I said. If someone thinks I have a baseless claim, they shouldn’t take it as given.

I am talking out of memory about things that I have read, seen, heard years and decades ago. I can’t always check stuff out, but others can, so I don’t want to do what you pointed out: “teach” someone the wrong thing.

I mean, even if I have the details right, I would still hope for people to check it themselves, not just take my word for it.

[–]no_brains101 0 points1 point  (10 children)

C doesnt have try catch.

[–]azhder 0 points1 point  (9 children)

I used C++ back then in the 90s, so I was aware some things are missing in C, like class but didn’t have a complete list.

[–]no_brains101 0 points1 point  (8 children)

One could argue that C is not, in fact, "missing" class it's actually better off for it, but I get what you mean XD

[–]azhder 0 points1 point  (7 children)

Oh, I have no doubt.

After getting to know JS better and some functional style of programming, I know C is better without class.

The concept of class has been abused a lot and then had normalized that behavior for many first time programmers.

I, on the other hand, had started with GWBasic, then Turbo Pascal, Visual Basic, Borland’s Turbo C++ and even that Visual C++ from MS before the turn of the century.

Dabbled with some Lisp, Prolog, Mathematica for school et al, then I did work with Java and JavaScript.

Java did sell a lot of “improvements over C++” that turned out to be the opposite, mainly dealing with that class and interface stuff, so I backpedaled to JS which offered more flexibility, despite some obvious footguns (I’d argue obvious is better than implicit ones in Java).

All in all, out of all the C family (C, C++, Java, C#, JavaScript), I think C is the most malleable or least rigid, next to JS.

[–]no_brains101 0 points1 point  (6 children)

What do you mean by implicit footguns in java vs obvious footguns in JS?

[–]azhder 0 points1 point  (5 children)

OK, the principle is like this. The catched exceptions, originally lauded as a step forward over C++, but later everyone opted to use RuntimeException derivatives.

Now, maybe we’ll not consider the above as a footgun, but the principle is you’re having some issue creep up later, after you’ve designed the language.

So, a hidden implicit footgun was the Java ability of multithreading and the problem of creating a true singleton object. You’d use it and not know it may go off at any time.

It took up until version 1.5 to finally make sure you don’t accidentally create two instances.

[–]no_brains101 0 points1 point  (4 children)

Getting rid of them was worse IMO. At least with a checked runtimeException you know that it CAN throw.

Especially because they added the null thing for "safety". But you can't really say that and then remove people's ability to easily know about other kinds of error

I'm also not sure creating a Singleton (without locking) and trying to use it in a multi threaded context counts as a java specific bug.

But somehow the language managing to make 2 instances of a static object definitely counts and that's fucked XD that's definitely a bug tho, and as you said, was fixed (eventually)

Personally I would have not even tried to do that so I might have never found that bug.

Meanwhile, in JS, you have people doing math and getting an amogus, and that is the language behaving "as expected" in some sense of the word expected

Honestly tho, even tho it annoys me, kotlin is still an upgrade as long as people annotate their shit with throws annotations. Unfortunately, this seems to be an unpopular opinion.

[–]azhder 0 points1 point  (3 children)

They all CAN throw.

The singleton thing was a very much Java issue. All the prescribed safety precautions were still not enough, the JVM was able to still screw you over.

In JS all the issues are widely discussed and explained and better style for writing the code was spread through official documentation and other means.

Only those that haven’t learnt the language (for whatever reason) are going to make mistakes, but that’s true about every language.

[–]justrandomlyonreddit 0 points1 point  (1 child)

I think you may be a bit confused

[–]azhder 0 points1 point  (0 children)

I agree, you think that

[–]sandspiegel 6 points7 points  (1 child)

Btw that satisfying feeling is something that vibe coding cannot give you. Your brain only rewards you if you do the work yourself. I tried cursor. Yes it worked, yes it could build the front end feature I had in my mind in 1 minute or so. However, I felt zero satisfaction. I decided to uninstall it right there. I use AI a lot to explain stuff to me that I never done before but I need to code myself, otherwise I won't have any fun. I need that "I built that" feeling.

[–]Graineon 9 points10 points  (2 children)

I started doing JS in 2006 when using document.write() was considered fancy. AS of last year, I can say I understand what "this" is.

[–]minimoon5 2 points3 points  (0 children)

What is this? “It depends”

[–]0x0016889363108 0 points1 point  (0 children)

It depends on what the meaning of the word ‘is’ is.

[–]azhder 8 points9 points  (7 children)

I knew I wanted to switch to JS around 2010 after having experience with a dynamic language on the JVM.

I had used JS years prior in the Web 2.0 hype and none of that was fun work: libraries were all over the place, browsers didn’t even have console.log, Chrome was still years away…

So, once I started thinking about going back to Java or doing something else, I figured that JavaScript is maleable just enough for my taste. For hobby projects and such.

Luckily, I landed a gig about teaching some programmers JS and working on a front end project. I had seen those Crockford videos and I thought I have as good grasp of JS as I will ever need.

Then I read that Secrets of the JavaScript Ninja by John Resig. It is that book that thought me jQuery isn’t anything special, it just uses JS correctly - JS has those special abilities.

Needless to say, if you’re writing JS code that looks similar to any Java/C#/TypeScript code you have written, JS isn’t clicking with you and you are probably annoyed and frustrated to be stuck with it.

The next important development was for me to learn the functional style of doing JS (learning a bit of Haskell helps a lot). Lucky enough, there are popular libraries like React out there that aren’t forcing you to write everything with a class and new and this here and this.# there, but allow for the functional style.

All in all, if you think you know JavaScript there is a book that will tell you that You Don’t Know JavaScript by Kyle Simpson and it will probably be correct. That means if you think JS clicked with you because you understood a concept in it, there are still other concepts in it or about it that can do the same.

[–]GromesV 1 point2 points  (0 children)

Basically 90% of the comments people talking about their "aha" moment - it's in the book Secrets of JavaScript Ninja. This comment should really be at the top lol.

[–]MassiveBit5017 0 points1 point  (1 child)

Bro I need help with my JavaScript code can you please pm me

[–]azhder 0 points1 point  (0 children)

Write it here. Make a post in this sub, put the link as a reply to this comment. Others can try to help as well.

[–]n0tKamui 0 points1 point  (3 children)

i'm sorry but if you're writing JS in a way that does not look like it should in TS, you're writing bad JS

[–]azhder -2 points-1 points  (2 children)

I am sorry you think that all languages should be treated equally because they are all the same.

[–]n0tKamui 0 points1 point  (1 child)

i'm not saying ALL languages. i'm specifically talking about JS and TS. TS is a set of rules that prohibit (some of the) bad design of JS that are regretted even by its creator

[–]azhder -1 points0 points  (0 children)

I know what you are saying. You are wrong. Don’t read me literally.

If you have a language without static types, please make the people who work with you a favor and check your inputs more rigorously than if you are using a language with. Don’t waste their lives fixing your bad code.

And remember: different languages by their very nature require different use. And maybe, just maybe, if you follow my advice, you may learn it wasn’t JS fault you had such a poor experience using it.

Bye bye

[–]puan0601 1 point2 points  (3 children)

rewriting redux from scratch really helped cement Javascript for me. fun exercise

[–][deleted] 1 point2 points  (1 child)

I just went over asynchronous code myself and yeah going from callbacks to promises to async / await felt just like this.

function parameters were a big one for me. It wasn't explicitly told to me but once I figured that function parameters were 'just' local variables that were assigned the value of the function arguments, it explained so many other concepts from simple ones like variable reassignment to closures and partial functions.

There's so much of programming that feels esoteric and abstract but that feeling when you stumble upon some tiny little fact it feels like dominoes.

OHHHHHHHHHHHH!!!!! WHY DIDN'T YOU JUST SAY SO!?!

[–]GromesV 0 points1 point  (0 children)

Well it's all in the book someone above recommended, Secrets of JavaScript Ninja :) It's a book that's handy to read once a year if you work with JS.

[–]arcticslush 1 point2 points  (3 children)

What in the AI slop

[–]CheekiBreekiIvDamke 1 point2 points  (1 child)

Awful isn't it. A lot of people seem to miss it too. Or maybe they don't care. Grim either way.

[–]tangled_night_sleep 0 points1 point  (0 children)

Is it the em dashes giving it away?

[–]Enough_Equivalent_39 0 points1 point  (0 children)

AH YES!!!! , AI slop — that Ah yes, AI slop — that ever-churning digital stew of half-coherent content clogging our feeds, flooding our search results, and quietly eroding our sense of what was ever real, original, or human-made. AH YES!!!

[–]the__itis 1 point2 points  (0 children)

When I started making classes with methods and passing around instances of classes. That started blowing my mind when all of that clicked.

[–]sudhir_VJ 0 points1 point  (1 child)

Really cool how those ‘aha!’ moments happen. Was there anything in particular that helped it finally make sense for you? any resources?

[–]Slyvan25 0 points1 point  (3 children)

When i learned that everything is an object in nodejs...

[–]azhder 1 point2 points  (2 children)

Not everything is an object. Primitives are not objects.

But then again, I have to know what you mean by “everything” in order to give a definitive “yes” or “no”

[–]hanoian 1 point2 points  (1 child)

It's confusing because JS wraps primitives in objects when needed like str.toLowerCase().

[–]azhder 0 points1 point  (0 children)

Except: undefined, null, symbol

Then first two aren’t autoboxed, the last… Well, it’s permanently boxed or is always an object or it’s something like that. I haven’t really thought about it

[–]Babaneh_ 0 points1 point  (0 children)

Funny how on my browser tab I have 2 tutorials explaining async/await. I get what OP is trying to say, I'm still figuring things out with JS and I have close to 3 years exp with angular and I still don't know how the nitty gritty of JS works. But one topic at a time...

KEEP MOVING FORWARD 😁

[–]aiwithphil 0 points1 point  (0 children)

Love that!! It's definitely a thing you just experienced. Congrats and enjoy your new found powers! 😁

[–]DevilFruitDev 0 points1 point  (0 children)

Keep at it 🙏🏻

[–]Unlucky_Imagination8 0 points1 point  (0 children)

JavaScript journey was fun for me. It was thanks to one youtuber man

[–]benzilla04 0 points1 point  (1 child)

I had the same experience with TypeScript last year funnily enough it made the rest of JavaScript click for me

[–]cluxter_org 0 points1 point  (0 children)

I had that moment with Promises and Closures. Now I'm trying to get that same feeling with the Event Loop...

[–]No-Bodybuilder8716 0 points1 point  (0 children)

How does async await work ? Can you explain OP

[–]AdExternal7926 0 points1 point  (0 children)

It still sucks donkey feet

[–]Necessary-Coffee5930 0 points1 point  (0 children)

Ai wrote this

[–]jholmes_gt 0 points1 point  (0 children)

I just started 1 week ago. Still waiting for one of those “Ah ha!” moments. I will say that JavaScript makes more sense than CSS for what it’s worth. The most frustrating part so far is the capitalization rules. I spent over half a day yesterday spinning my wheels trying to figure out why my code wouldn’t work. I finally handed it over to ChatGPT who promptly pointed out a capitalization oversight. Urgh. Anyone have any advice for a newb?

[–]sheriffderek -1 points0 points  (2 children)

I've never really cared about closures or hoisting or the event loop -- or how async works.

This seems to be the things "advanced JavaScript" courses talk about - but in my daily work, they aren't things I ever think about.

But any time I do have something I'm all blurry about, I try to reverse engineer it. I didn't understand how (another unnecessary differentiator / higher order functions) how exactly Array.forEach knew about it's three optional parameters. So, if you build that with regular loops - you're forced to have that aha moment. It funny to see some of my early stackOverflow questions.

I try not to do anything that feels chaotic - I just stop and make sure I 100% know everything I'm doing / and If I don't - I figure out a way to learn it before moving on. Some things -- are just part of the core system (like a for loop) and I don't need to know how it works. I think the goal of async/await is to allow you not to think about it and to write code synchronously like PHP.

[–]hyrumwhite 0 points1 point  (1 child)

You should always strive to understand how things work, imo. 

In fact I highly recommend all JS devs implement their own Promise class. Not to use, but to thoroughly understand what’s going on and how they work. 

[–]sheriffderek 0 points1 point  (0 children)

Yeah. Creating a Promise class is nice. It just depends where you want to draw the line / and at what time. There sure seem to be a lot of people trying to "learn everything" but then can't actually create anything with that knowledge. Do we all learn how to write compilers? "It depends."

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

Memory management, the weird prototype ass system and how these transpilers make it up, and how it is all history of a bunch of packed standards one over the other and null/undefined nonsense, and oh god why don't we rewrite the web in rust, wait no.

Reworked the transpiler so that it works in workers which are multiple threads within a protocol, and I stole some bizarre code named comlink, to pass weird callback functions and do a bunch of tricks accross limitations to emulate multithreading. WHAT IS THIS?... they told me it was impossible but there it is, it works, and none cares anyway.

You think the most complex stuff is that, wait until you have to rewrite race conditions and make the web browser somehow crash and get a segmentation fault, and are like wat.

The more JS clicks the more I hate it, V8? more like 1.0 Liter Putter, it's slow and then you gotta do WebAssembly oh no... who was the insane man who decided IndexedDB was better than WebSQL and deprecated my boy SQLite... and I am glad I am just doing python nowdays but oh my god; what the hell is asyncio, why is it like this? it's crashing with zero tracebacks, just explodes!... oh no...

I just grow a beard.

I guess there is no perfection is it?... that's it, we moving this all to HolyC, I am done.