Functions - A Brief History
In the advent of programming, we created our systems using routines and subroutines. This, later, transformed to the creation of systems using programs, subprograms and functions. And, these days, we're only left with functions, at least that's what the majority of the programming community knows and works with everyday.
What are Functions? Why are they needed?
Functions are a group of statements, packaged as a single entity, that performs a certain task. They can be called upon or "invoked" many times. They can receive zero or more inputs and return zero or more outputs.
For example, let's say we want to square a few numbers.
An implementation without the use of functions would look like this:
var number2 = 2;
var square_of_number2 = number2 * number2;
console.log(square_of_number2);
var number3 = 3;
var square_of_number3 = number3 * number3;
console.log(square_of_number3);
Now, let's look at an implementation that is created using functions:
function square(number){
return number*number;
}
var square_of_number2 = square(2);
var square_of_number3 = square(3);
The code looks so much cleaner just by comparing the above two methods.
Advantages of Creating Functions
- Code looks clean and organized.
- DRY principle is followed.
- Enable reuse of code in the program.
Ways of creating Functions in JS
There are 4 ways of creating functions in JavaScript, each with their own unique subtleties. The order below denotes my preference of using these methods, from most used to never used.
- Function Declarations (always named)
- Function Expressions (can be named or anonymous)
- Arrow Functions (always anonymous)
- Using
Function
constructor (don't ever do it; security reasons and performance issues)
Function Declaration
To quote MDN ,
A function definition (also called a function declaration, or function statement) consists of the function keyword, followed by:
- The name of the function.
- A list of parameters to the function, enclosed in parentheses and separated by commas.
- The JavaScript statements that define the function, enclosed in curly brackets, {...}.
In other words, if any JS statement starts literally with the function
keyword, then it's a Function Declaration.
Why prefer using Function Declaration?
- Standard syntax (found across languages)
- Only way to define a function which hoists
- Has a name attached to it; more readable error stack traces
console.log(calculateSquare(2)); // hoisting
// OUTPUT: 4
function calculateSquare(number) {
return number * number;
}
Parameters & Arguments
The placeholder which accepts a value as an input in the function is called a Parameter.
When declaring a function, we specify it's parameters.
In the previous example code, number
is a parameter.
The value passed into the function while it's being invoked is called an argument.
In the previous example code, the value 2
is an argument.
Default Parameters
Parameters can be assigned a default value. This default value is used when an argument value isn't passed into the function or if undefined
is passed.
function defaultParamFunction(param1 = 'some value') {
console.log(param1);
}
defaultParamFunction(); // no argument is passed
// OUTPUT: 'some value'
defaultParam('overridden'); // argument is passed
// OUTPUT: 'overridden'
Function Expressions
A different approach to creating a function is by using the Function Expressions syntax.
These can be of 2 types: Named Function Expressions and Anonymous Function Expressions.
Named Function Expressions are very uncommon. Very rarely encountered but should be used the most.
// named function expression
const variable_name = function function_name() {
console.log("Hello World");
}
// anonymous function expression
const another_variable_name = function () {
console.log("Hello World");
}
My advice is to always name any and all functions expressions. The same reasoning that is used for why one should always use function declaration follows here.
Why use named function expressions?
- More self documenting code
- More debuggable stack traces
IIFEs (Immediately Invoked Function Expressions)
As the name suggests, these are function expressions which are invoked/called immediately where they're defined.
The syntax involves wrapping the function into a set of parentheses () and then invoking it with another set of parentheses ().
// function definition is wrapped in parentheses
( function immediately_invoked() {
console.log("Hello World");
} )(); // notice the invoking set of parentheses
Arguments can also be passed to IIFEs.
(
function iife(param1) {
console.log(param1);
}
)(1); // argument 1 passed here
Arrow Functions
With arrow functions, function
keyword isn't used to define a function. Instead, a fat arrow =>
is used to define a function.
Arrow functions are anonymous by definition.
// syntax for defining an arrow function
const function_name = () => { // more characters
// function body
}
// syntax for a normal function declaration
function function_name() { // less characters
// function body
}
Don't use arrow functions as a generic replacement of function declaration just because they seem shorter to write. Because if we just compare the two defined functions in the above example, it's clearly visible that arrow functions take more characters to write them as compared to writing the same function in Function Declaration way (compare the characters in the first line of declaration).
Don't use Arrow Functions. Why?
- They are syntactically anonymous which means while debugging, stack traces show errors in these functions as "Anonymous Function"
- It doesn't have a
this
keyword. It bindsthis
lexically.(More about this in future posts) - They only seem shorter at a glance but take almost as much as or more characters than a function declaration.
Arrow Function IIFEs
IIFEs can also be defined using the arrow function syntax.
// notice the first wrapping parenthesis
(
() => {
console.log("Hello World");
}
)();
Function Constructor
Functions can also be created using the Function Constructor syntax. But, it's advised not to use this syntax at all unless absolutely necessary. This creates function dynamically in the scope and these functions are only available to be called in the global scope.
// syntax
const variable_name = new Function('arg1', 'arg2', ..., 'argN', 'functionBody');
For example:
const square_number = new Function('number', 'return number*number;');
console.log(square_number(2));
// OUTPUT: 4
Fun fact: Function constructor can be invoked with or without the new
keyword.
Summary
Declaration vs Expression vs Arrow
// 01 Function Declaration
function function_name() {
// body
}
// 02-a Function Expression (Named)
var variable_name = function function_name() {
// body
}
// 02-b Function Expression (Anonymous)
var variable_name = function() {
// body
}
// 03 Anonymous Arrow Function
var variable_name = () => {
// body
}
// 04 Function Constructor
var variable_name = new Function('param_name', 'function body');
To summarize, there are 4 different ways of creating functions in JavaScript.
But, (in my opinion) prefer using Function Declaration over other types of function designs. Named Function Expression can also be used. Don't use Anonymous Function Expression and Arrow Function unless absolutely necessary and definitely not as a generic replacement for Function Declaration. Never use Function Constructor to create a function.
Top comments (0)