Functions
Functions are one of the fundamental building blocks in JavaScript or any programming language for that matter. A function in JavaScript is similar to a procedure, a set of statements that performs a task or calculates a value, but for a procedure to qualify as a function, it should take some input and return an output where there is some obvious relationship between the input and the output. To use a function, you must define it somewhere in the scope from which you wish to call it.
Calling Functions
A function within scope can be called by simply using its name and parameters if it has any. Functions are hoisted so it doesn't matter where it is called, but good programming practice would be to declare the function in the code before calling it. There are other ways to call functions. There are often cases where a function needs to be called dynamically, or the number of arguments to a function vary, or in which the context of the function call needs to be set to a specific object determined at runtime.
Functions Are Objects
It turns out that functions are themselves objects, and in turn, these objects have methods. The call() and apply() methods can be used to achieve this goal.
Functions & Scope
Functions must be in scope when they are called, but the function declaration can be hoisted (appear below the call in the code). The scope of a function declaration is the function in which it is declared (or the entire program, if it is declared at the top level).
The scope of variables and functions depend upon where they are placed within the hierarchy of the code. Variables and functions declared at the root level of the code are global. The scope of variables and functions declared within a closure are only available within the closure unless they are exposed to the outside.
Function Arguments
The arguments of a function are not limited to strings and numbers. You can pass whole objects to a function. The showProps() function (defined in Working with objects) is an example of a function that takes an object as an argument.
Expression Function
Function expressions are convenient when passing a function as an argument to another function.
Object Parameters
Function As A Parameter
Recursion
Recursive functions are functions that call themselves. Recursive functions must have an exit condition or they will run until they run out of memory and crash.
Recursion & The Stack
Recursive functions use something called the "call stack". When a program calls a function, that function goes on top of the call stack. This is similar to a stack of books. You add things one at a time. Then, when you are ready to take something off, you always take off the top item.
Recursion uses the stack to keep track of states. Each recursive call that doesn't meet the exit condition will push its state onto the stack. When the exit condition is met, it starts popping the stack.
Recursion Debugging
Recursive functions can be difficult to debug. The easiest way to work through the code is by keeping track of what is on the stack. Consider the following recursive function call.
Iteration | Action | The Stack |
---|---|---|
1 | The parameter 0 is not greater than or equal to 5, so it is placed on the "call stack" and a recursive call is made to loop(0+1 = 1) |
0 |
2 | The parameter 1 is not greater than or equal to 5, so it is placed on the "call stack" and a recursive call is made to loop(1+1 = 2) |
1 0 |
3 | The parameter 2 is not greater than or equal to 5, so it is placed on the "call stack" and a recursive call is made to loop(2+1 = 3) |
2 1 0 |
4 | The parameter 3 is not greater than or equal to 5, so it is placed on the "call stack" and a recursive call is made to loop(3+1 = 4) |
3 2 1 0 |
5 | The parameter 4 is not greater than or equal to 5, so it is placed on the "call stack" and a recursive call is made to loop(4+1 = 5) |
4 3 2 1 0 |
6 |
The parameter 5 is equal to 5, the exit condition is met, so the return statement is called, The code upon return that is executed is the code following the recursive call, In this function there is no code, so the "call stack" is popped until it's empty. |
3 2 1 0 |
7 | The "call stack" is popped. |
2 1 0 |
8 | The "call stack" is popped. |
1 0 |
9 | The "call stack" is popped. |
0 |
10 | The "call stack" is empty. | (Empty Call Stack) |
Getting all the nodes of a tree structure (such as the DOM) is easier via recursion
Binary Tree
A binary tree is a data structure in which nodes that have lesser value are stored on the left while the nodes with a higher value are stored at the right.
Function Scope & Closure
Functions form a scope for variables—this means variables defined inside a function cannot be accessed from anywhere outside the function. The function scope inherits from all the upper scopes. For example, a function defined in the global scope can access all variables defined in the global scope. A function defined inside another function can also access all variables defined in its parent function, and any other variables to which the parent function has access. On the other hand, the parent function (and any other parent scope) does not have access to the variables and functions defined inside the inner function. This provides a sort of encapsulation for the variables in the inner function.
Anonymous Function Expression
The following function expression has an anonymous function. An anonymous function has no name assigned to it. This is a function expression, but there are other types of functions without any name. The begging question in that case is how are they called. The answer is that they are invoked immediately.
IIEF - Immediately Invoked Expression Function
An Immediately Invoked Function Expression (IIFE) is a code pattern that directly calls a function defined as an expression. It looks like this:
It is a design pattern which is also known as a Self-Executing Anonymous Function and contains two major parts:
- The first is the anonymous function with lexical scope enclosed within the Grouping Operator (). This prevents accessing variables within the IIFE idiom as well as polluting the global scope.
- The second part creates the immediately invoked function expression () through which the JavaScript engine will directly interpret the function.
Instead of saving the function in a variable, the function is immediately invoked. This is almost equivalent to just writing the function body, but there are a few unique benefits:
- It creates an extra scope of variables, which helps to confine variables to the place where they are useful.
- It is now an expression instead of a sequence of statements. This allows you to write complex computation logic when initializing variables.
All variables and functions defined within the anonymous function are not available to the code outside of it, effectively closing the code off; sealing itself from the outside world. This is known as closure.
The following code will fail because the function calls are made outside of the closure and they are out of scope at the global level.
Exposing Embedded Functions
Passing Items Into Closure
One of the cool things about this, is that you can name the exposed method or variable whatever you like.
This can be helpful in avoiding name conflicts.
You can pass items into the closure by including them in the immediate invoked function expression and in
the function parameters.
The Module Pattern
Rest Parameters
The rest parameter syntax allows a function to accept an indefinite number of arguments as an array, providing a way to represent variadic functions in JavaScript. In mathematics and in computer programming, a variadic function is a function of indefinite arity, i.e., one which accepts a variable number of arguments.
A function definition's last parameter can be prefixed with ... (three period characters), which will cause all remaining (user supplied) parameters to be placed within an Array object.
There are some additional syntax restrictions:
- A function definition can only have one rest parameter.
- The rest parameter must be the last parameter in the function definition.
- Trailing commas are not allowed after the rest parameter.
- The rest parameter cannot have a default value.
Rest Parameters vs The Arguments Object
arguments is an array-like object accessible inside functions that contains the values of the arguments passed to that function.
There are four main differences between rest parameters and the arguments object:
- The arguments object is not a real array, while rest parameters are Array instances, meaning methods like sort(), map(), forEach() or pop() can be applied on it directly.
- The arguments object has the additional (deprecated) callee property.
- In a non-strict function with simple parameters, the arguments object syncs its indices with the values of parameters. The rest parameter array never updates its value when the named parameters are re-assigned.
- The rest parameter bundles all the extra parameters into a single array, but does not contain any named argument defined before the ...restParam. The arguments object contains all of the parameters, including the parameters in the ...restParam array, bundled into one array-like object.
Arrow Functions
An arrow function expression is a compact alternative to a traditional function expression, with some semantic differences and deliberate limitations in usage:
- Arrow functions don't have their own bindings to this, arguments, or super, and should not be used as methods.
- Arrow functions cannot be used as constructors. Calling them with new throws a TypeError. They also don't have access to the new.target keyword.
- Arrow functions cannot use yield within their body and cannot be created as generator functions.
The map() method of Array instances creates a new array populated with the results of calling a provided function on every element in the calling array. The map() method is an iterative method. It calls a provided callbackFn function once for each element in an array and constructs a new array from the results.
In this case the callback function is the arrow function.
Predefined Functions
JavaScript has several top-level, built-in functions:
eval() | The eval() method evaluates JavaScript code represented as a string. |
---|---|
isFinite() | The global isFinite() function determines whether the passed value is a finite number. If needed, the parameter is first converted to a number. |
isNaN() | The isNaN() function determines whether a value is NaN or not. Note: coercion inside the isNaN function has interesting rules; you may alternatively want to use Number.isNaN() to determine if the value is Not-A-Number. |
parseFloat() | The parseFloat() function parses a string argument and returns a floating point number. |
parseInt() | The parseInt() function parses a string argument and returns an integer of the specified radix (the base in mathematical numeral systems). |
decodeURI() | The decodeURI() function decodes a Uniform Resource Identifier (URI) previously created by encodeURI or by a similar routine. |
decodeURIComponent() | The decodeURIComponent() method decodes a Uniform Resource Identifier (URI) component previously created by encodeURIComponent or by a similar routine. |
encodeURI() | The encodeURI() method encodes a Uniform Resource Identifier (URI) by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character (will only be four escape sequences for characters composed of two "surrogate" characters). |
encodeURIComponent() | The encodeURIComponent() method encodes a Uniform Resource Identifier (URI) component by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character (will only be four escape sequences for characters composed of two "surrogate" characters). |
escape() | The deprecated escape() method computes a new string in which certain characters have been replaced by a hexadecimal escape sequence. Use encodeURI or encodeURIComponent instead. |
unescape() | The deprecated unescape() method computes a new string in which hexadecimal escape sequences are replaced with the character that it represents. The escape sequences might be introduced by a function like escape. Because unescape() is deprecated, use decodeURI() or decodeURIComponent instead. |