This is the third blog post out of the twenty-one blog series. Coz of course the book has 21 chapters. These blogs sum up my learning from the book EloquentJS.
Let's say you are writing a blog...if you used a new English word it would be deemed wrong. But while writing a piece of code and writing a new word here is indispensable...Gives a lot of power right?
A function is created with an expression that starts with the keyword function. Functions have a set of parameters( or not)and a body, which contains the statements that are to be executed when the function is called. The function body of a function created this way must always be wrapped in braces, even when it consists of only a single statement.
Some functions produce a value, and some don’t.
A return statement determines the value the function returns. When control comes across such a statement, it immediately jumps out of the current function and gives the returned value to the code that called the function. A return keyword without an expression after it will cause the function to return undefined.
Bindings and Scopes:
Each binding has a scope, which is the part of the program in which the binding is visible.
For bindings defined outside of any function or block, the scope is the whole program—you can refer to such bindings wherever you want. These are called global For bindings defined outside of any function or block, the scope is the whole program—you can refer to such bindings wherever you want. These are called global variables.
But bindings created for function parameters or declared inside a function can be referenced only in that function, so they are known as local bindings.
Having these kinds of bindings give isolation to functions.
Bindings declared with let and const are in fact local to the block that they are declared in.
Function As Values:
A function binding usually simply acts as a name for a specific piece of the program. Such a binding is defined once and never changed.
A function value can do all the things that other values can do. It is possible to store a function value in a new binding, pass it as an argument to a function, and so on.
The function keyword is used at the start of a statement.
The preceding code works, even though the function is defined below the code that uses it. Function declarations are not part of the regular top-to-bottom flow of control.
Arrow functions were added in 2015, mostly to make it possible to write small function expressions in a less verbose way.
Instead of the function keyword, it uses an arrow (=>) made up of an equal sign and a greater-than character.
It expresses something like “this input (the parameters) produces this result (the body)”.
When an arrow function has no parameters at all, its parameter list is just an empty set of parentheses.
The Call Stack:
Let's say a function was called and the controller went to place x, Because a function has to jump back to the place that called it when it returns, the computer must remember the context from which the call happened.
The place where the computer stores this context is the call stack. Every time a function is called, the current context is stored on top of this stack.
Storing this stack requires space in the computer’s memory. When the stack grows too big, the computer will fail with a message like “out of stack space” or “too much recursion”.
What if you give extra arguments to a function or too little arguments?
It ignores the extra arguments and computes the square of the first one.
If you pass too few, the missing parameters get assigned the value undefined.
What happens to local bindings when the function call that created them is no longer active?
Local bindings are created anew for every call, and different calls can’t trample on one another’s local bindings.
This feature—being able to reference a specific instance of a local binding in an enclosing scope—is called closure.
A good mental model is to think of function values as containing both the code in their body and the environment in which they are created. Not in which it is called.
It is perfectly okay for a function to call itself, as long as it doesn’t do it so often that it overflows the stack. A function that calls itself is called recursive.
The dilemma of speed versus elegance is an interesting one. You can see it as a kind of continuum between human-friendliness and machine-friendliness. Almost any program can be made faster by making it bigger and more convoluted. The programmer has to decide on an appropriate balance.
Therefore, always start by writing something that’s correct and easy to understand.
Recursion is not always just an inefficient alternative to looping. Some problems really are easier to solve with recursion than with loops. Most often these are problems that require exploring or processing several “branches”, each of which might branch out again into even more branches.
The first is that you find yourself writing similar code multiple times. You’d prefer not to do that. Having more code means more space for mistakes to hide and more material to read for people trying to understand the program. So you take the repeated functionality, find a good name for it, and put it into a function.
The second way is that you find you need some functionality that you haven’t written yet and that sounds like it deserves its own function. You’ll start by naming the function, and then you’ll write its body. You might even start writing code that uses the function before you actually define the function itself.
Functions and Side Effects:
Functions can be roughly divided into those that are called for their side effects and those that are called for their return value.
Functions that create values are easier to combine in new ways than functions that directly perform side effects.
A pure function is a specific kind of value-producing function that not only has no side effects but also doesn’t rely on side effects from other code. Non-Pure ones rely on side effects and also have side effects. Although its nothing wrong to write not-pure functions.