Writing Javascript – Functions for newbie
Hello!
This is a question that might be stupid, but trying to wrap my head around writing JS is taking it's toll.
So look at this code block from codecademy JS intro course, using function as a parameter inside another function:
Is there a structural convention that the higher-order function is declared first? Logically in my head you would declare the anotherFunc first, then the higherOrderFunc, because that is using the other one. As a metaphor: Baking a cake you would get all specific ingredients ready first, then put it all together.
This is just a question out of curiosity, and trying to understand the "unwritten rules", because I know they are as important as actual coding ...
28 Replies
have you tried running it and seeing what happens when you flip the declaration order?
The same result ...
It prints: I just invoked anotherFunc as a callback function!
I would agree that anotherFunc should go above higherOrderFunc. It makes sense to have dependencies below and higherOrderFunc is relying on anotherFunc
Programs where reading top to bottom never coming across something that hasn't been declared yet are really nice to work with and they organise themselves
there's no dependency though, the connection between
higherOrderFunc
and anotherFunc
doesn't exist until the last line of the codeblock. They're both defined, and just sitting there in memory, and then anotherFunc
is passed as an argument to higherOrderFunc
there could be half a dozen other justAnotherFunc
and yetMoreFunc
, and they'd all be valid parameters for higherOrderFunc
in practice, those probably won't even be declared in the same fileIt's not a true dependency but it's still an unknown when you come across it reading top to bottom
While if you have anotherFunc above you've at least seen it before the thing that uses it
but
anotherFunc
isn't mentioned in higherOrderFunc
No but it's still passed to it
yes, after you've read both function definitions
Also if this was written in Typescript you'd want to type
param
and you're going to end up with a type for a function that hasn't been seen yetregardless, it's a bit of a moot point. It's very uncommon to write a callback and a function that takes that callback in the same file. A lot of the time, the callbacks will just be defined inline when you call the function
I guessed I would start an infinite loop when asking this question ...
My basic question is really – and this is obviously theoretical, not practical: Would a boss go mental if I wrote it the other way around, because of an unwritten convention?
And of course, this is from a beginners course ...
Use whichever order the style guide says, or if it's your project whatever order you prefer
it's a demonstration of a principle that you won't run into in production code in quite this way
and even if a manager or senior takes issue, they'll just tell you and you can reverse them
Great! Thank you both!
One has to take some kind of course for learning, and I know these issues of "understanding" will come up, but its just good to get it aired out for my own sake ...
@Å Marlon G the order would only become relevant had you used
anotherFunc()
literally inside higherOrderFunc
.
Since it's passed as a parameter it only needs to be available at runtime.
As Jochem suggested, each could be in their own import module.
They only need to be available (loaded) if the compiler hits the higherOrderFunc(anotherFunc);
line.
I disagree that callbacks are rarely in the same file as their caller or only appear as inline functions. It depends on the callback's job and scope. You could have a single DOM event handler or helper to serve multiple callees all in the same file.
Enjoy writing Promises then 😋still doesn't matter actually, unless you call
higherOrderFunc
before defining anotherFunc
works perfectly fine
This complains about accessing anotherFunc
before initialization thoughyour second example is what I meant by "available at runtime".
For the same reason it would bail on the next line containing
${param.name}
however...
would work again 🙂mostly because javascript's scoping is a mess 😄
(to explain, defining something with the
function
keyword hoists the declaration to the top of the file at runtime)
((Also when you use the var
keyword, the variable initialization (though not assignment) is hoisted. But don't use var
in 2023 ever, only villains do that))debugging JS was so much more fun before there was
let
and const
...
"Where's the var? Where is it? Come here..."
Just remember: those who know the rules are also free to bend them at their will.I think the main take away is indeed that scoping is quiet tricky to grasp ...
This is the section of the course which addresses abstraction concepts, and it gives the example that by saying "I baked a cake" implies a lot of actions that we understand without it having to be explained directly (like mixing ingredients, pre-heating the oven, etc.).
Therefore it is also the task of learnign to be specific and precise (and naming things ...), which gives me the most headache ...
But interestingly, in my former life, I had to learn sign language for a dance piece, and sign language is in many ways a bit similar to coding.
You can't really imply things in the same way as you can with spoken language, and therefore it is very precise and concise. As an example, signing "I rode the bike yesterday" you would first establish riding a bike, and then you could use that variable, so to speak, and say in what context you did it (yesterday).
In practice, at least as much as I can remember, you would place the "the riding bike" variable visually over your right shoulder, for example, and then point to it for reference, and then sign the "yesterday".
... hmm ... so this means when writing: moves that declaration before all other code which itself is not a function?
And: is this true only when using the keyword, meaning that all functions written with => is not moved to the top, or are all functions regardless of how you write them moved to the top?
You don't use the equals sign with the function keyword, but other than that it's correct. Only ones declared with function are moved
Changed it to parenthesis, in case some other newbie was reading this. 💩
So, basically in a JS file, all the functions declared with function is run first, is that the practical meaning of this?
And What about the => functions? Are they run in order, or are there more of these prioritizing effects?
Finally – why is it done this way? What's the practical use of this?
they're not run, they're defined
and it's likely a leftover from previous versions of javascript maintained for backwards compatibility
you can technically use it, but I wouldn't recommend it. The way modern JS is used, most things are defined in imports so it's not something to worry too much about
Ah, ok ... so it's like the baking cake metaphor, they are just prepared to be run in order later.
prepared to be run when called, yes. In the baking metaphor, the JS engine reads the entire recipe and then sets aside certain ingredients (
function
and var
) ahead of time so they're accessible later. The rest is just grabbed from storage as they're neededSo, just for a practical example:
Say i wanted a CMS where clicking a button added a new page to the tree structure.
Clicking the button runs a script creating the new page and giving option of what type of page to create (blog post, e.g.), but the construction of the page is a separate JS file with the instructions of how the page should look like (images, heading, h1, h2, etc.).
The button click runs the script addpage.js, which is importing script from blogpage.js
And within blogpage.js all the different elements mentioned are there own variables, functions, whatever, waiting to be run when called upon.
... in the right ballpark?
yeah, pretty much
Cool! 🥳