who, what, why, where, when, and how. All about JavaScript Functions.

who, what, why, where, when, and how. All about JavaScript Functions.

Why Do we need functions?

Functions serve as a way to encapsulate a set of instructions into a single unit that can be invoked and reused throughout your code. Imagine you have a block of code that you use repeatedly. (Alright... alright... Don't leave, this article is worth a read. Just stick around for a little while.) Instead of copying and pasting it every time, you can place it within a function and simply call that function whenever you need to execute that code. This not only promotes code reusability but also enhances the readability and maintainability of your codebase, making it easier to manage, debug, and update as your project grows.

How to declare a function?

FunctionName is like a nickname you give someone – it helps you recognize and call them. Just like you might say "Adarsh" or "heyBaby!"

In some situations, functions can work without a name at all, so keep that in mind.

Difference between Function Declaration &

Definition?

You've probably heard programmers say, "I've declared a function" or "I've defined the function." These phrases are pretty much the same thing.

Now, let's take the next step and declare a function ourselves.

function printMe(){
console.log('printing...')
}

To make this function work, you need to 'call' or 'invoke' it. Think of how you call someone in real life – you use their name. Right? Similarly, to use our function, you simply call it by its name.

But here's the catch: if you just write the function's name in JavaScript, it won't give you the result you expect. Instead, you'll see the entire function body as a "string" version of the function definition.

To get the desired result, you must use parentheses () after the function name.

What is the difference between Parameters and arguments?

Now, let's dig into a key concept: parameters and arguments. Think of parameters as variables waiting to be filled in a function, and when we use the function, we provide actual values, which are the arguments.

It's a bit like when you ask a friend for money, you ask a particular amount (parameter), and they start abusing you (argument). So, let's put this into practice by adding parameters to our function and passing in argument values.

How to define Function Expressions?

Now that we've got a grip on a function declaration and passing values, let's explore another method of defining functions using a function expression.

Think of function expression as assigning value to a variable.

For those who might not be familiar, JavaScript has three types of variables:

  1. const: This is used for values that won't change.

  2. let and var: These are used for values that can change. We'll dive deeper into these when we explore function scope, but for now, let's keep it at that.

So, in a function expression, we're kind of swapping out variables with functions. variable name turning into the function's name, and instead of a regular value, we're putting an entire function in its place

const printMe = function(){
console.log("this is function expression");
}

printme()

//output:
//this is function expression

Now, let's take our understanding of function expressions a step further by using parameters and arguments.

const printMe = function(a,b,c,d,e,f) {
console.log(a,b,c,d,e,f);
}

printMe(10,20,30,40,50,60)

If you're paying close attention, you might have realized that we can treat functions as values in JavaScript. In programming languages that treat functions as values, these functions are referred to as first-class citizens.

How to return from a function

Imagine we have two functions: Function X and Function Y. Each of them is skilled at doing their own thing.

Now, let's say Function X completes its task and produces a result. Instead of letting that result vanish into thin air, we can save it for later. This saved result can be used when we call Function Y.

function x(){
/*-----------------
---Their own task--
-------------------*/
}
const p = x(); //saving for future use 

function y(){
/*-----------------
---Their own task--
-------------------*/
}

Now, let's dive into the code to gain a deeper understanding. Go through each step with specific numbers, making it easier to grasp the concept more effectively.

What are default parameters?

What if the function doesn't return any value?

For example, if you forget to provide the necessary arguments that a function expects, the function will still execute, but the function's execution will result in a special value called "undefined" or "nan" (not a number).

That brings us to our new topic Default Parameters.

We can use the default parameters value for a function if it's required to safeguard it from an unnatural value returning from the function. Let's understand better with the code.

Now what will happen if we only pass one argument?

Now in this case you are not passing the second argument, So b will be undefined

So we can safeguard our parameters with some kind of default values, something that you like.

What are Rest Parameters?

The rest parameter is something that allows a function to accept any number & infinite number of arguments as an array.

Just remember, you can use only one rest parameter and it must be the last one in the list of parameters.

How to define Arrow Functions?

Arrow functions or fat-arrow syntax we know how to define a function with the function expression.

const add = function (x,y){
return x+y;
}

Let's take a look at converting a regular function expression to an arrow function, with a few adjustments that you have to make.

If the arrow function body contains just one statement, you can skip adding curly braces.

const add = (x,y) => x+y;

And if you're dealing with just one parameter, you can leave out the parentheses as well.

const add = x => x;

What is the Execution context in JavaScript?

Whenever a function is executed it creates its imaginary container. Imagine each function as having its little room. This room holds everything the function needs while it's working. It's like a workspace where the function can access its tools (variables and functions) and look out the window to see what's happening around it (scope chain). This setup ensures that each function can do its job without getting mixed up with other functions.

How scopes are different in variables?

In JavaScript, we commonly use three types of variables, Let's delve into these differences with some code examples

var, let, and const. var was introduced in ES5, and let and const were introduced in ES6.

Variables declared with var have a function scope, making them accessible throughout the entire function they're declared in.

variables declared with const have block scope, limiting their visibility to the specific block or curly braces {} in which they are defined.

var attaches itself to the global window object, which can lead to data leakage and global variable interference across different parts of your code or even other pages.

let and const, are more localized and prevent unintended global scope issues.

What is a window object?

JavaScript can use certain features that aren't even included in the programming language itself. These functionalities are made available by browsers like Chrome, Safari, and others through objects like the window object.

console, prompt, onclick etc. are all components of the window object. While they're not built directly into JavaScript itself, they are provided by browsers.

We can use them in our JavaScript code to enhance our web applications, even though they're not a fundamental part of the core JavaScript language.

It's worth noting that there are additional objects beyond the window object as well.

JavaScript Browser Object Model - Studytonight

What are Nested Functions?

What does nested mean? We know how to define a function

In JavaScript, you can make a function inside another function. This is like the first puzzle piece for understanding something cool called 'closure.' And if you're curious about closures, start by getting comfortable with nested functions – that's one function inside another.

Let's find out why we're seeing a 'ReferenceError,' which brings us to our next topic: function scope.

What is the scope of a Function?

Let's make it clear. You've got to know two important rules, especially if you're digging into closures. Ready?

  1. Variables Scoped Within Functions: Variables that are defined inside a function can not be accessed outside of the function.

  1. The opposite of it: A function can access anything and everything inside the scope it is defined.

Function scope is about what variables a particular function can access. If you have a variable defined inside a function, it's like a secret that only that function knows. Other functions can't peek into that secret unless it's shared.

Take A Break GIFs | Tenor

What is Lexical Scope?

Let's use code to make this clearer. It's all revision boys!

All the details about which function can access which variables and how the scope hierarchy is structured are stored in something called the lexical environment. It's like a map that keeps track of who can access what, ensuring that each function knows its scope boundaries and which variables it can reach. This lexical environment is a behind-the-scenes assistant that helps JavaScript keep everything organized and prevents variables from wandering where they shouldn't be.

How does the Scope Chain work?

If one scope needs to use a certain variable but cannot find it in the scope, it will look up in the scope chain and check whether it can find a variable on one of the outer scopes. If the variable is available in the outer scope, then the child scope has access to it. If it is not there in any outer scopes, the JavaScript will throw a reference error. So this process is called variable lookup.

Let's understand better with some code.

We're invoking the getPersonInfo function, which returns a string containing the values of the name, age and city variables:

First, memory space is set up for the different contexts. Understand context as some rooms. The scope chain gets created when the execution context (like here getPersonInfo() is called ) is created, meaning it's created at runtime! and each room is like a mini-environment that holds variables and functions.

Mainly there are two types of contexts in the scope chain: the global context and local contexts (execution contexts) created when functions are called.

We have the default global context (window in a browser, global in Node), and a local context for the getPersonInfo function which has been invoked. Each context also has a scope chain.

For the getPersonInfo function, the scope chain looks something like this (don't worry, it doesn't have to make sense just yet):

The scope chain is like a "sequence of references" (connections) to objects. These objects contain information about references to values and other scopes that can be accessed within a specific part of your code.

What will happen when it tries to access the city?

Alt Text

JS engine doesn't give up that easily: it works hard for you to see if it can find a value for the variable city in the outer scope that the local scope has a reference to until it hits the global object.

Alt Text

Now that we have a value for the variable, the function getPersonInfo can return the string Sarah is 22 and lives in San Francisco

Let's take another code as an example.

Alt Text

It's almost the same, however, there's one big difference: we only declared a city in the getPersonInfo function now, and not in the global scope. We didn't invoke the getPersonInfo function, so no local context is created either. Yet, we try to access the values of name, age and city in the global context.

(Rule 2: You can go to outer scopes, but not to more inner... scopes.)

Alt Text

Quick Recap:

  1. JavaScript starts looking for a variable from where you're standing.

  2. If it doesn't find it, it goes up one level in the scope chain and checks again.

  3. This repeats until the variable is found or it reaches the global scope.

What are Closures?

Closure is nothing but a nested function.

YARN | | | Video gifs by quotes | 0f0c6828 | 紗

Wait! Wait! Why all the hype about the closure then?

Closure understanding depends on your understanding of nested functions & function scopes.

  1. Closures are functions that have access to variables from another function's scope. This is accomplished by creating a function inside another function.

  2. A Closure is a function that returns another function.

  3. A Closure is an implicit, permanent link between a function and its scope chain.

    So, closure is nothing but a nested function.

What we basically do in closure is call the outer function, specify an argument, and then leverage both the inner and outer functions together.

Now what will happen if I call outer function in the same code with an argument?

So what does outerReturn now contains?

Though the execution of x is over, the value that we have passed through the outer function still lives inside the inner function.

A closure is a way in JavaScript that a function can remember and access its outer variables, even after the function has finished executing. It's like a little memory bubble that lets functions hold onto things they need, even if they're done doing their main job. So, closures are like JavaScript's superpower for managing data and making sure functions play nice with each other.

What is a callback function?

  • We have created functions: function definition

  • We have assigned functions: function expression

  • We have defined functions in another function: Nested functions

Now we are going to pass the function as a parameter to another function.

if bar had been a string I would have printed it, right? If it was a number I could have done maths around it. So if it is a function then I can execute it. Right?

How do I execute this?

Now I know that foo takes a function, so I can pass a function to it.

A callback function is a function that is passed as an argument to another function and is intended to be executed later.

We can do this more directly by using anonymous functions.

Notice, that we have created a function without any name, this function is called an anonymous function, If you remember our chat on "how we declare functions?", this might ring a bell.

setTimeout

It is a built-in JavaScript function that allows you to schedule the execution of a function after a specified amount of time. It's basically what we learned with a time delay feature.

So, now this code will run after 10 seconds. It will come in handy when we learn Async programming.

Now just to make it all things clear. We will improvise our previous example with setTimeout.

What are higher-order Functions?

A higher-order function is a special type of function that does one of two things: it either takes another function as an input or returns a function as its output.

You might recall this concept from our discussion on callback functions, where we touched on the idea. However, not all callback functions are necessarily higher-order functions.

If you're curious to learn more, you can explore topics like pure and impure functions, as well as Immediately Invoked Function Expressions (IIFE) on your own.

Keep this blog as a reference because I might update more function-related concepts of JS in this blog. Happy learning!

Special thanks: Lydia Hallie