Reviewing Eloquent Javascript #Chpt3
Unveiling the Depths of JavaScript Functions: A Journey through Eloquent JavaScript Chapter 3
In this blog, I will write on my learnings from the Eloquent Javascript Book's Chapter 3: Functions.
Here's the PDF for Eloquent Javascript Book's Chapter 3.
Why are functions so Important?
Functions are a crucial concept in pretty much any programming language. A function is a group of statements that performs a particular task. Functions allow us to repeat tasks that involve a similar sequence of steps (processing).
Functions allow us to reuse code and create different modules to perform some procedures we plan on using repeatedly (solution to the problem of code duplication).
A complex problem is generally more managable when broken down into simpler subproblems. Then the program will be easier to understand and to update than the sequntial one.
Function Declaration
A function is created with an expression that starts with the keyword function.
The parentheses themselves are always required for every function you defined ( irrespective of the way you define the function ) and they allow you to receive arguments that would be input to your function.Then we have curly braces, curly braces surround the function body and that is the code which executes when this function gets called.
The code works, even when the function is defined below the code ( function call ) that uses it. Function declarations are not part of the regular top-to-bottom flow of control.
let result = divide(20 / 2); function divide(x, y) { return x * y; }
Functions accept outside values. We can do that by defining a function with parameters. Parameters are the input to the function. Parameters are variables listed in the function declaration that are specified inside
()
by the name. Parameters to a function behave like regular variables, but their initial values are given by the caller of the function, not the code in the function itself. These variables in our casex
&y
are re-created every time a function is called.We can pass default value to the parameters. When we give default value to the parameter, the value of that expression will replace the argument only when it is not given.
function divide(x, y = 3) { return x * y; } console.log(divide(15)); // 5 console.log(divide(15, 5)); //3
Each value is assigned to a parameter in the order they are defined. Parameters are the variables declared in a function and the values that are passed to that function are called arguments.
If you expect the function to give back some value in return , it should include a return statement (which is done by using the keyword
return
), followed by the value you want to be returned. This return value can be of any type (number, string, etc).A return keyword without an expression after it will cause the function to return undefined. Functions that don’t have a return statement at all, similarly return undefined. Remember: Any statements after return statement won't be executed.
Example:
function divide(x, y) { return x * y; } // there is no semicolon here (not required)
Function Expressions
The functions that are defined using an expression is called as function expressions which are stored in a variable.
They are followed by an optional function name, a list of parameters in a pair of parenthesis
(parameter1, ..., parameterN)
and a pair of curly braces{ ... }
that has the body of the function.Functions that are stored in variables do not need function names. They are always called using the variable name.
Example:
let divide = function( x, y ){ return x / y; } let result = divide(10 / 2);
As we know that in function expressions, function name is optional so the function that are declared without the function names are also called as anonymous functions.
It is easy to confuse the function declaration and function expression. The way you can remember is function declaration always starts with the keyword function on the other hand function expression always starts with declaring the variable name of the function.
Arrow Functions
An arrow function is defined using a pair of parenthesis and the the list of parameters
(parameter1,..., parameterN)
, followed by a fat arrow=>
and curly braces{...}
that has the body statements.let greetings = () => "Hello World!";
When the arrow function has only one parameter, the pair of parentheses can be omitted. We don't need the
function
keyword, thereturn
keyword, and the curly brackets.let greetings = val => { console.log("Good Morning " + val); };
When it contains a single statement, the curly braces can be omitted too.
let greetings = val => "Good Morning " + val;
Scope of a variable
Global Scope: Variables declared Globally (outside any function) have Global Scope.
Local Scope: Variables declared Locally (inside a function) have Function Scope.
Block Scope: let & const have block scope. Variables declared with var keyword cannot have block Scope. Variables declared inside a block {} have Block scope and cannot be accessed from outside the block of code.
Example:
//Global let num1 = 10; var num2 = 20; const num3 = 30; function myScope(){ // Function Scope let num1 = 100; var num2 = 200; const num3 = 300; console.log('Function Scope: ', a, b, c); // Function Scope: 100 200 300 } myScope(); console.log('Global Scope: ', a, b, c); // Global Scope: 10 20 30
Example 2:
//Global let num1 = 10; var num2 = 20; const num3 = 30; if(true){ // Block Scope let num1 = 100; var num2 = 200; const num3 = 300; console.log('Block Scope: ', a, b, c); // Block Scope: 100 200 300 } console.log('Global Scope: ', a, b, c); // Global Scope: 100 20 30
Variables created for function parameters or declared inside a function can be referenced only in that function, so they are known as local variables.
let a = 10; let b = 20; function add(a, b) { console.log('Function Scope', a, b); return a + b; } add(100, 200); add(1000, 2000); console.log('Global Scope', a, b); //Output // Function Scope 100 200 // Function Scope 1000 2000 // Global Scope 10 20
Every time the function is called, new instances of these bindings are created. This provides some isolation between functions—each function call acts in its own little world (its local environment).
Lexical Scoping: A lexical scope in JavaScript means that a variable defined outside a function can be accessible inside another function defined after the variable declaration. But the opposite is not true; the variables defined inside a function will not be accessible outside that function.
let x = 2; let add = function() { let y = 1; return x + y; }; console.log(add()); //3
Call Stack
JavaScript uses a call stack to manage (keep track of) script that calls multiple functions.
The call stack works based on the LIFO principle i.e., last-in-first-out.
When you execute a script, the JavaScript creates a Global ( main() ) and pushes it on top of the call stack.
Whenever a function is called, the JavaScript creates a saving point for the function, pushes it on top of the Call Stack, and starts executing the function.
If a function calls another function, the JavaScript creates a new saving point for the function that is being called and pushes it on top of the call stack.
When the current function completes, the JavaScript pops it off the call stack and resumes the execution where it left off in the last code listing.
The script will stop when the call stack is empty.
Example:
function greetings() { say(); } function say() { return "Good Morning"; } greetings();
Illustration of the overall status of the Call Stack in all steps:
Closures
In other programming languages we can't access variable that are outside of a function inside of that function. But in JavaScript it is possible because anything that is inside has access to the things that is outside of his scope. For example:
let name = "Prerana"; function whatsyourname(){ console.log(name); } whatsyourname(); //Output: //Prerana
Variable
name
that has the Global scope is accessed inside of a function scope and therefore this is also a Closure.People often misunderstood that closures are functions inside functions but that's not true the main idea behind closer is that they give access to an outer function score from the inner function. Let's take one example form the book:
function multiplier(factor) { return number => number * factor; } let twice = multiplier(2); console.log(twice(5)); // → 10
So what's happening in this function? First let's make this change little bit beginner friendly.
function multiplier(factor) { console.log("Factor is: " + factor); return function(number) { console.log("Factor is: " + factor); console.log("Number is: " + number); return number * factor; } } let twice = multiplier(2); console.log(twice(5)); // Output // Factor is: 2 // multipler() function // Factor is: 2 // inner function // Number is: 5 // 10
Here we are passing argument
2
to the parameterfactor
in themultiplier()
function then the multiplier function is returning a function which we are storing in the variabletwice
.As we know, functions that are stored in variables do not need function names. So, we are calling it using the variable name
twice
and passing it argument5
. Hence,2
get multiplied by5
and returns10
.But the main thing to understand here is that, this entire code is a closure as we are accessing the
factor
variable inside the inner function as well.Another Example:
function getUrl(url){ fetch(url).then(() => { console.log(url); }); } getUrl(someURL);
This is also a closure as we are accessing
url
inside of the arrow (inner) function even if the outer function (getUrl()
) has finished executing and those variables are no longer accessible outside of that function because the function insidethen
will only execute after the fetch function has ran.
Recursion
Recursion is when a function calls itself. So, you might start thinking now, when doing so we might run into an infinite loop but that's not true. Always remember, recursion is similar to normal loops as here also we have some exit condition that will take us outside the loop so the function stops calling itself.
Here's an example:
function factorial(num, total = 1) { if( num <= 1) { return console.log("The Factorial is " + total); } return factorial(num-1, total * num); } factorial(4); // The Factorial is 24
Here inside the function, we are declaring a condition that will help us to jump out of the loop.
So, first we are passing
factorial(4, 1)
as the if condition is false the console.log() won't run and then our recursion line runs.We return
factorial(3, 4)
again the if condtion is false so the recursion will run that returnsfactorial(2, 12)
.As the
num
is still2
the if condition won't run and we will returnfactorial(1, 24)
.After this finally , as the num is equal to 1 the if condition will run and return the statement
"The Factorial is 24 ".
So that's all these are my key Learning from the Chapter 3 of Book Eloquent Javascript. Also, Please do share your key learning from the Chapter 2 and what did you understood the most.
This is a blogging challenge from #teamtanayejschallenge
Here's a link to the Website: ejs-challenge.netlify.app
References:
Thank you very much for the patience. I’d love to hear your feedback about the post. Let me know what you think about this article, and javascript in general, through my Twitter and LinkedIn handles. I would love to connect with you out there!
Peace!