K O logo
Web Development

Project WebApp — Functional programming with JavaScript

Author

Kalle

Date Published

This AI-generated image showcases a neatly arranged workspace centered around a large computer monitor displaying lines of code. The desk is organized with books, a coffee mug, a yellow desk lamp, and a few potted plants, creating a warm and inviting atmosphere. Behind the monitor, a wall is covered with various diagrams and keywords related to programming concepts such as "Pure Functions," "Map," "Reduce," "Filter," and "Immutability." The visual style is clean and modern, with a strong focus on coding and functional programming themes, blending educational elements with a cozy workspace vibe.

As the name "functional programming" suggests, this lesson has a heavy focus on functions. In JavaScript, you can describe a function in several ways:

  • with the function keyword:
1function func(params){
2 ...doSomething...
3 return result
4}
  • as a method (same behavior as the function keyword):
1const methodHolder = {
2 func(params){
3 ...doSomething...
4 return result
5 }
6}
  • store it as an anonymous function in a variable
1const func = function(params) {
2 ...doSomething...
3 return result
4}
  • and the best part: define it as an arrow function
1const func = (params) => {
2 ...doSomething...
3 return result
4}

Arrow functions have some benefits over the classical function/method declaration.

  1. the this context gets set at the time of definition
  2. it's a bit shorter to write (with only one parameter you can even omit the parentheses)

A short excursion on why this is weird in JS:

In the programming model of JavaScript it is totally fine to redefine the owner of a function when you call it, so whenever you use this, you have to make sure that the context is set correctly when you call the function.

A short example:

1var person = {
2 name: "Clara",
3 greet() {
4 return "Hello " + this.name;
5 },
6};
7person.greet(); // -> 'Hello Clara'
8
9var greet = person.greet;
10greet(); // -> 'Hello '
11
12greet.call({ name: "Peter" }); // -> 'Hello Peter'
13greet.call({ noPerson: 500 }); // -> 'Hello undefined'

To solve this, like always, you have several possible ways to go.

  1. Avoid this-context by using direct access to the owning object (BAD):
    1var person = {
    2 name: "Clara",
    3 greet() {
    4 return "Hello " + person.name;
    5 },
    6};
    7person.greet(); // -> 'Hello Clara'
    8
    9var greet = person.greet;
    10greet(); // -> 'Hello Clara'
    11
    12greet.call({ name: "Peter" }); // -> 'Hello Clara'
    13greet.call({ noPerson: 500 }); // -> 'Hello Clara'
  2. Use a class and arrow-function for a fixed this-context:
    1class Person {
    2 constructor(name) {
    3 this.name = name;
    4 this.greet = () => "Hello " + this.name;
    5 }
    6}
    7var person = new Person("Lotte");
    8person.greet(); // -> 'Hello Lotte'
    9var greet = person.greet;
    10greet(); // -> 'Hello Lotte'
    11
    12greet.call({ name: "Peter" }); // -> 'Hello Lotte'
    13greet.call({ noPerson: 500 }); // -> 'Hello Lotte'
  3. Go functional and use an independent greeting function:
    1const greet = (name) => "Hello " + name;
    2greet("Bert"); // -> 'Hello Bert'

The lesson-learned should be, only use this if you really have to, when possible use pure functions.

Now back to functional programming.

One fundamental building block is the usage of "pure" functions, this definition is close to the mathematical definition of functions f(x) -> y. A pure function returns a value purely defined by the parameters passed into it, and there should be no dependencies to variables defined outside of the function's scope. The returned value is also always the same if the passed parameters are the same (no randomness or hold state in the function). Besides calculating the resulting value the function has no other effects. So never ever mutate the incoming values.

  • pure or impure? pure
    1function f(x, y) {
    2 return x + y;
    3}
  • pure or impure? impure
    1let count = 0;
    2function f(x, y) {
    3 count++;
    4 return x + y;
    5}
  • pure or impure? impure
    1const y = 2;
    2const f = (x) => x + y;
  • pure or impure? pure
    1const f = (x, y) => x + y;
  • pure or impure? impure
    1const f = (x, y) => {
    2 console.log(x, y);
    3 return x + y;
    4};
  • pure or impure? pure
    1const f = (x) => x + 2;

Another very important paradigm in functional programming is "declarative programming". Instead of describing the control flow of the program you should care about the logic and behavior. For example use recursion instead of loops.

Task

  • write a pure and declarative function calculating of the fibonacci sequence as a start use this imperative and impure implementation:
1let a, b, temp;
2const fibonacci = (num) => {
3 a = 1;
4 b = 0;
5 while (num >= 0) {
6 temp = a;
7 a = a + b;
8 b = temp;
9 num--;
10 }
11
12 return b;
13};


Here is a codesandbox with tests to work on this in the browser: Edit Fibonacci

solution

Passing functions around

The parameters passed into a function can be data, like numbers, booleans, strings, objects... and also functions. So you can call a function with a function. Even the returned value can be a function.

The image features a man smiling with braided hair (Xzibit), overlaid with the text: "YO DAWG, I HERD YOU LIKE FUNCTIONS, SO I PUT FUNCTIONS IN YOUR FUNCTIONS SO YOU CAN CALL FUNCTIONS WHILE YOU PRODUCE FUNCTIONS." The text is a humorous take on nested functions in programming.

Functions taking other functions as arguments or returning functions are called "higher-order-functions"

Getting back to the greeting function, this pattern allows you to define a function to return a function to generate a greeting message for a specific name.

1const generateGreetingFunction = (name) => {
2 return () => "Hello " + name;
3};
4const greetDavid = generateGreetingFunction("David");
5greetDavid(); // -> 'Hello David'

or in a shorter way:

1const generateGreetingFunctionShort = (name) => () => "Hello " + name;

The most commonly used higher-order-functions in JS are array-functions like forEachfiltermap and reduce. Those functions take a function as input and call this function with every element of the array.

Examples:

1const tatooineResidents = people
2 .filter((person) => {
3 return planets.some(
4 (planet) => planet.id === person.homeworld && planet.name === "Tatooine",
5 );
6 })
7 .map((person) => person.name);

Edit Star Wars API - data transform exercises

Tasks:

  • get familiar with the array functions
  • get all starships with a hyperdrive rating over 2 which appear in the movie "A new Hope"
  • are there any transports capable of carrying more than 8 passengers which are cheaper than 400000 credits
  • how fast is the TIE bomber?
  • how many characters are listed for the movie "The Phantom Menace"?
  • list all the characters from the movie "Revenge of the Sith" matched to their species
  • what is the longest opening crawl of all movies?

solution

 This AI-generated image depicts a highly organized and visually appealing workspace with a strong focus on React.js development. The scene is centered around a large computer monitor displaying code and a central React logo, accompanied by a laptop also displaying code. The desk is cluttered with various items including an open notebook filled with diagrams, a coffee mug, sticky notes, plants, and a blue desk lamp. The wall behind the monitor features several React logos, along with terms like "UseState," "UseEffect," and "UseContext," which are key concepts in React. The overall aesthetic is modern and tech-focused, with a consistent blue and yellow color scheme that ties all elements together, emphasizing a clean and productive coding environment.

Project WebApp — From code to UI - Introduction to React.JS

Get started with React by learning to create UI components using JSX. This introduction covers the basics of setting up a React environment, creating simple components, and understanding JSX syntax. Learn how to build interactive web applications efficiently with practical examples.

Mailing List

If you want to receive updates on new posts, leave your email below.