JS: Functions

JS: Functions

In details introduction to JavaScript functions.

ยท

14 min read

In computer programming, a function is a self-contained block of code that performs a specific task. Functions can take input in the form of parameters or arguments, and they can return values as output. They provide a way to modularize code and avoid redundancy.

Importance

In JavaScript, functions are incredibly important and powerful. JavaScript functions can be declared using the function keyword and can be assigned to variables or objects as values. Functions can also be passed around as arguments to other functions and can be returned as values from functions.

JavaScript functions can be used for a wide range of tasks, such as:

  1. Code Modularity - Functions allow you to divide your code into smaller, more manageable chunks, making it easier to organize and debug.

  2. Code Reusability - Once you have defined a function, it can be reused in different parts of your code, reducing the amount of code you need to write.

  3. Encapsulation - Functions can also help you to encapsulate your code, protecting it from external interference and making it easier to debug.

  4. Callbacks - JavaScript functions can be used as callbacks, allowing you to execute code after an event has occurred or after an asynchronous operation has completed.

In short, functions are at the core of JavaScript and are essential to creating complex and dynamic web applications. Understanding functions in JavaScript is crucial for any programmer looking to become proficient in the language.


Function Declaration

The most common way to declare a function is using a function declaration. This involves using the function keyword followed by the function name, parameters (if any), and the function body. Function declarations are hoisted, meaning they can be used before they are declared in the code.

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

Function Expression

Function expressions involve assigning a function to a variable or property. This can be done using anonymous functions or named functions. Function expressions are not hoisted and cannot be used before they are defined.

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

const obj = {
  multiply: function(x, y) {
    return x * y;
  }
};

Arrow Function

Arrow functions are a shorthand syntax for writing functions in JavaScript. They use an arrow => instead of the function keyword, and often allow for more concise code. They are ideal for writing inline functions and for functions that don't require a this binding.

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

const multiply = (x, y) => {
  return x * y;
};

Best Practice

In modern JavaScript, it is best practice to use function expressions or arrow functions over function declarations. This is because function declarations can lead to potential issues with hoisting and can make code harder to read and debug. Additionally, the use of let and const for variable declaration should be preferred over using var.

When using function expressions or arrow functions, it is recommended to use descriptive variable and function names that follow the camelCase naming convention. It is also important to properly comment and document your code for readability and maintainability.


Functional programming

Functional programming is a programming paradigm that emphasizes the use of functions to solve problems. JavaScript is a language that supports many functional programming features. Here are some examples of functional programming features in JavaScript:

Pure Functions

A pure function is a function that produces the same output for the same input and has no side effects. In other words, it does not modify anything outside of its scope. This makes the function easier to reason about and test.

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

const result = add(2, 3);
console.log(result); // 5

Higher-Order Functions

A higher-order function is a function that takes one or more functions as arguments or returns a function as its result. Higher-order functions are useful because they allow for the creation of more abstract and reusable functions.

function multiplyBy(factor) {
  return function(number) {
    return number * factor;
  }
}

const double = multiplyBy(2);
const triple = multiplyBy(3);

const result1 = double(4);
const result2 = triple(4);

console.log(result1); // 8
console.log(result2); // 12

Immutable Data

Immutable data is data that cannot be modified after it has been created. This can help prevent bugs and increase the predictability of a program.

const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4];

console.log(arr1); // [1, 2, 3]
console.log(arr2); // [1, 2, 3, 4]

In the example above, we are using the spread operator to create a new array arr2 that includes all the elements of arr1 plus the number 4. The original arr1 remains unchanged.

Recursion

Recursion is a technique in which a function calls itself. This can be useful for solving problems that can be broken down into smaller sub-problems.

function factorial(n) {
  if (n === 0) {
    return 1;
  } else {
    return n * factorial(n - 1);
  }
}

const result = factorial(5);

console.log(result); // 120

In the example above, we are using recursion to calculate the factorial of a number. The factorial function calls itself with a smaller input until it reaches the base case of 0. The final result is the product of all the previous numbers.

Best Practice

When using functional programming in JavaScript, it is important to write pure functions as much as possible. This can help ensure that your functions are predictable and easy to test. Additionally, using higher-order functions and immutable data can make your code shorter and more concise. However, it is important to balance the benefits of functional programming with the needs of your specific application.


Function Chain

Chaining functions is one of the most powerful features of functional programming. In JavaScript, you can chain functions together by returning an object or a value from a function and then calling another function on it. This is also known as method chaining.

Here is an example of how to chain functions in JavaScript:

const numbers = [1, 2, 3, 4, 5];

const result = numbers
  .map(number => number * 2)
  .filter(number => number > 5)
  .reduce((accumulator, currentValue) => accumulator + currentValue);

console.log(result); //16

In the example above, we are starting with an array of numbers [1, 2, 3, 4, 5]. We then chain together three functions: map, filter, and reduce, to manipulate the data and return a single result.

First, we call the map function to double each number in the original array. This returns a new array of [2, 4, 6, 8, 10].

Next, we call the filter function to remove all numbers less than or equal to 5. This returns a new array of [6, 8, 10].

Finally, we call the reduce function to calculate the sum of the remaining numbers. This returns a single value of 24.

By chaining these three functions together, we are able to manipulate the data in a complex way with just a few lines of code.

To create a chain of functions, one must:

  1. Start with an initial value or data structure

  2. Call the first function on the initial value or data structure

  3. Return a result from the first function

  4. Call the next function with the result from the previous function

  5. Repeat steps 3 and 4 until all the desired functions have been called

  6. The result of the last function is the final result of the chain

It's important to note that not all functions can be chained, and some functions that are chainable may have different return values depending on how they are used in a chain. Therefore, when creating a chain of functions, it's important to understand the behavior of each individual function and how they can be combined to achieve the desired result.


Closures

A closure is created when a function is defined inside another function and it has access to the outer function's variables and parameters, even after the outer function has returned. In other words, a closure is a function that "remembers" the environment in which it was created.

Here is an example of a closure in action:

function outerFunction() {
  const name = "Alex";

  function innerFunction() {
    console.log(`My name is ${name}`);
  }

  return innerFunction;
}

const result = outerFunction();
result(); // Output: My name is Alex

In the example above, outerFunction returns innerFunction. When outerFunction is called, it creates a local variable name and a function innerFunction. innerFunction is then returned and assigned to the result variable.

When result is called later with result(), it calls innerFunction which is still able to access the name variable, even though outerFunction has already returned.

The local context bound of a closure refers to the scope in which the closure was created. In other words, a closure can access variables defined in its own scope, as well as variables defined in any scopes above it.

In the example above, innerFunction is a closure that has access to the name variable defined in outerFunction. However, if we were to define another function outside outerFunction, that function would not have access to name.

function outerFunction() {
  const name = "Alex";

  function innerFunction() {
    console.log(`My name is ${name}`);
  }

  return innerFunction;
}

function anotherFunction() {
  const name = "Sarah";
  console.log(`My name is ${name}`);
}

const result = outerFunction();
result(); // Output: My name is Alex
anotherFunction(); // Output: My name is Sarah

In this modified example, the name variable defined in anotherFunction is not accessible within outerFunction or innerFunction. Similarly, the name variable defined in outerFunction is not accessible within anotherFunction.

Closures are a powerful concept in JavaScript and are commonly used when writing functions that need to "remember" information from previous executions, like event handlers or callbacks. However, care must be taken with closures to avoid unintended memory leaks or unexpected behavior caused by variable scoping.


Core Functions

In JavaScript, core functions are functions that are part of the language itself and are available without needing to import or require any additional libraries or modules. These functions are built into the JavaScript runtime environment and can be used directly in your code.

Here are the main types of core functions in JavaScript, along with some examples of each type:

1. Array Functions

Array functions are used to manipulate arrays in JavaScript.

FunctionDescription
Array.from()Creates a new array from an array-like object or iterable.
Array.isArray()Checks whether a value is an array.
Array.of()Creates a new array with a variable number of arguments.
Array.prototype.concat()Joins two or more arrays and returns a new array.
Array.prototype.every()Checks if every element in an array passes a test.
Array.prototype.filter()Creates a new array with all elements that pass a test.
Array.prototype.find()Returns the value of the first element in an array that passes a test.
Array.prototype.findIndex()Returns the index of the first element in an array that passes a test.
Array.prototype.forEach()Calls a function for each element in an array.
Array.prototype.includes()Checks whether an element is present in an array.
Array.prototype.indexOf()Returns the index of the first occurrence of an element in an array.
Array.prototype.join()Joins all elements of an array into a string.
Array.prototype.lastIndexOf()Returns the index of the last occurrence of an element in an array.
Array.prototype.map()Creates a new array with the results of calling a function for each element in an array.
Array.prototype.pop()Removes the last element from an array and returns that element.
Array.prototype.push()Adds one or more elements to the end of an array and returns the new length.
Array.prototype.reduce()Applies a function against an accumulator and each element in an array to reduce it to a single value.
Array.prototype.reduceRight()Applies a function against an accumulator and each element in an array, starting from the right, to reduce it to a single value.
Array.prototype.reverse()Reverses the order of elements in an array.
Array.prototype.shift()Removes the first element from an array and returns that element.
Array.prototype.slice()Extracts a section of an array and returns a new array.
Array.prototype.some()Checks if at least one element in an array passes a test.
Array.prototype.sort()Sorts the elements of an array.
Array.prototype.splice()Adds or removes elements from an array.
Array.prototype.toLocaleString()Converts an array to a localized string.
Array.prototype.toString()Converts an array to a string.
Array.prototype.unshift()Adds one or more elements to the beginning of an array and returns the new length.
Array.prototype.valueOf()Returns the primitive value of an array.

2. Number Functions

Number functions are used to manipulate numbers in JavaScript.

FunctionDescription
Number.isFinite()Checks whether a value is a finite number.
Number.isInteger()Checks whether a value is an integer.
Number.isNaN()Checks whether a value is NaN (Not-a-Number).
Number.isSafeInteger()Checks whether a value is a safe integer.
Number.parseFloat()Converts a string to a floating-point number.
Number.parseInt()Converts a string to an integer.
Number.prototype.toExponential()Converts a number to an exponential notation string.
Number.prototype.toFixed()Formats a number using fixed-point notation.
Number.prototype.toLocaleString()Converts a number to a locale-specific string.
Number.prototype.toPrecision()Formats a number to a specified precision.
Number.prototype.toString()Converts a number to a string.
Number.prototype.valueOf()Returns the primitive value of a number.

3. String Functions

String functions are used to manipulate strings in JavaScript.

FunctionDescription
String.fromCharCode()Returns a string created from the specified sequence of Unicode values.
String.fromCodePoint()Returns a string created from a specified sequence of Unicode code points. Available since ES6.
String.prototype.charAt()Returns the character at a specified index in a string.
String.prototype.charCodeAt()Returns the Unicode value of the character at a specified index in a string.
String.prototype.codePointAt()Returns the Unicode code point at a specified index in a string. Available since ES6.
String.prototype.concat()Joins two or more strings and returns a new string.
String.prototype.endsWith()Checks whether a string ends with a specified substring. Available since ES6.
String.prototype.includes()Checks whether a string contains a specified substring. Available since ES6.
String.prototype.indexOf()Returns the index of the first occurrence of a specified value in a string.
String.prototype.lastIndexOf()Returns the index of the last occurrence of a specified value in a string.
String.prototype.localeCompare()Compares two strings in the current locale.
String.prototype.match()Searches a string for a match against a regular expression, and returns the matches.
String.prototype.normalize()Returns the Unicode Normalization Form of a string. Available since ES6.
String.prototype.padEnd()Pads a string with a specified character(s) until the specified length. Available since ES6.
String.prototype.padStart()Pads a string with a specified character(s) until the specified length. Available since ES6.
String.prototype.repeat()Returns a new string containing a specified number of copies of an existing string. Available since ES6.
String.prototype.replace()Searches a string for a specified value, or a regular expression, and returns a new string where the specified values are replaced.
String.prototype.search()Searches a string for a specified value, or a regular expression, and returns the position of the match.
String.prototype.slice()Extracts a section of a string and returns a new string.
String.prototype.split()Splits a string into an array of substrings.
String.prototype.startsWith()Checks whether a string starts with a specified substring. Available since ES6.
String.prototype.substring()Extracts the characters from a string between two specified indices.
String.prototype.toLocaleLowerCase()Converts a string to lowercase according to the host's locale.
String.prototype.toLocaleUpperCase()Converts a string to uppercase according to the host's locale.
String.prototype.toLowerCase()Converts a string to lowercase.
String.prototype.toString()Returns a string representing the specified object.
String.prototype.toUpperCase()Converts a string to uppercase.
String.prototype.trim()Removes whitespace from both ends of a string.
String.prototype.trimEnd()Removes whitespace from the end of a string. Available since ES2019.
String.prototype.trimStart()Removes whitespace from the beginning of a string. Available since ES2019.
String.prototype.valueOf()Returns the primitive value of a string.

These are just some examples of the many core functions available in JavaScript. Depending on your needs, you may find that other core functions are more useful.


Conclusion

In conclusion, functions are a fundamental concept in programming and essential building blocks for creating complex programs. They allow us to organize code into modular and reusable units, improving code readability and maintainability. Functions in programming languages like JavaScript can also be passed around as values, which opens up new possibilities for writing code in a more functional style.

Functional programming is a paradigm that puts a strong emphasis on functions as the primary means of writing programs. The goal of functional programming is to write code that is declarative, predictable, and easy to reason about. By avoiding mutating states and using pure functions, functional programming helps to reduce bugs, increase code reuse, and make software more robust.

However, functional programming is not a silver bullet and may not always be the best choice for every situation. Programmers need to have a strong understanding of both functional and imperative programming paradigms, and when to use each one.

Ultimately, the power of functions lies in the ability to take complex problems and break them down into smaller, more manageable pieces. With a strong foundation of functions, programming becomes a more expressive and enjoyable experience, and programmers can create software that is both efficient and fun to use.


Resources:

  1. MDN Web Docs - The JavaScript Guide: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions

  2. Eloquent JavaScript: https://eloquentjavascript.net/

  3. JavaScript.info: https://javascript.info/function-basics

  4. W3Schools - JavaScript Functions: https://www.w3schools.com/js/js_functions.asp

  5. FreeCodeCamp - JavaScript Basics: https://www.freecodecamp.org/news/javascript-basics-for-beginners/#functions


Disclaim: This article was created in a rush with ChatGPT.


I hope you have learned a lot. Have a nice day ๐Ÿ‘‹

ย