DEFAULT PARAMETERS

Example -

PASSING AS ARGUMENTS (PRIMITIVES VS NON-PRIMITIVE DATA-TYPES)

When we pass a primitive data-type as an argument to a function, the function makes a COPY of the original value, and works with it.
On the other hand, when we pass a non-primitive data-type as an argument to a function, the function makes a copy of the REFERENCE that points to the place in the memory where the object is stored. This copy points to the value itself. Because of all this, the original object can be modified from inside of a function.
We should never change the values of non-primitives like objects inside a function, because that can have unforseeable circumstances.

Also, JavaScript is again different as,
In programming languages, Arguments can be passed by value, or passed by reference.
JS does not have passing by reference, only passing by value...
If pass by reference was there in JS, then value of NON-PRIMITIVE data-types could also be changed from inside the function.

FIRST-CLASS FUNCTIONS -

It means that functions are simply values and just another type of objects. Therefore -
We can store functions in variables or as object methods.
We can pass functions as arguments in other functions.
We can return functions from functions.
We can call methods on functions.

HIGHER-ORDER FUNCTIONS -

It basically is a function that recieves a func as an arguement or it returns a func or both.

Example -

AN EXAMPLE OF FUNCTION RETURNING FUNCTION -

THE CALL, APPLY AND BIND METHOD

CALL METHOD -
It is a method that is applied to function because functions are objects. Here the first argument defines that what should "this" keyword be equal to.

APPLY METHOD -
Same as call method, only diff is that, second argument is an array of the arguments.

BIND METHOD -
This method does not call the function to which it is attached, instead it returns a new function where the "this" keyword is permanently set.

Note - If we try to save the call or apply method, we will get an error, because call() invokes a function immediately, whereas bind() creates a copy of the function with a preset value of 'this'.
If we want to call a function later with preset arguments, then we use bind() method.

With Event Listeners

Partial application -
This means some of the arguments of a function are predefined.

IIFE - Immediately Invoked Function Expression

It's just a function expression that is only executed once.
We have to wrap the function expression around ().
IIFEs were used for data privacy, i.e., to not allow certain variables to be modified from the global scope. Since variables declared with var, let or const are function-scoped, that's why we used IIFEs to define certain variables that cannot be modified from the global scope.
Example -

Variables declared with let or const are block scoped as well, so we can use that as well for data privacy.

CLOSURES

A CLOSURE makes a function remember all the variables that existed at the function's birthplace.

The secret of the closure is basically this - Any function always has access to the variable environment of the execution context in which the function was created.

The closure is the VARIABLE ENVIRONMENT attached to the function, exactly as it was at the time and place that the function was created.

Closure has a priority over scope chain, i.e., if a variable does not exists in the local scope of a, the function will look for the variable first in the closure then in the parent scope/s.

IMPORTANT - Closures contains variables from all levels of scope chain.

More examples of closures