In the previous chapter we saw what functional programming is all about. We saw how functions in the software world are nothing but mathematical functions. We spent a lot of time discussing how pure functions can bring us huge advantages such as parallel code execution, being cachable, and more. We are now convinced that functional programming is all about functions.
In this chapter we are going to see how functions in JavaScript can be used. We will be looking at the latest JavaScript version, ES7/8. This chapter is a refresher on how to create functions, call them, and pass arguments as defined in ES6 and later versions. That’s not the goal of this book, though. We strongly recommend that you try all the code snippets in the book to get a gist of how to use functions (more precisely we will be working on arrow functions).
Once we have a solid understanding of how to use functions, we will be turning our focus to seeing how to run the ES8 code in our system. As of today, browsers don’t support all features of ES8. To tackle that, we will be using a tool called Babel. At the end of the chapter we will be starting our groundwork for creating a functional library. For this purpose, we will be using a node project that will be set up using the Babel-Node tool to run our code in your system.
Note
The chapter examples and library source code are in branch chap02. The repo’s URL is https://github.com/antsmartian/functional-es8.git
Once you check out the code, please check out branch chap02:
...
git checkout -b chap02 origin/chap02
...
For running the codes, as before run:
...
npm run playground
...
ECMAScript: A Bit of History
- 1.
ECMAScript 1 was the very first version of the JavaScript language, released in 1997.
- 2.
ECMAScript 2 is the second version of the JavaScript language, which contains very minor changes with respect to the previous version. This version was released in 1998.
- 3.
ECMAScript 3 introduced several features and was released in 1999.
- 4.
ECMAScript 5 is supported by almost all browsers today. This is the version that introduced strict mode into the language. It was released in 2009. ECMAScript 5.1 was released with minor corrections in June 2011.
- 5.
ECMAScript 6 introduced many changes, including classes, symbols, arrow functions, generators, and so on.
- 6.
ECMAScript 7 and 8 have new concepts like async await, SharedArrayBuffer, trailing commas, Object.entries, and so on.
We refer to ECMAScript as ES7 in this book, so these terms are interchangeable.
Creating and Executing Functions
In this section we are going to see how to create and execute functions in several ways in JavaScript. This section is going to be long and interesting as well. Because many browsers do not yet support ES6 or higher versions, we want to find a way to run our code smoothly. Meet Babel, a transpiler that can convert the latest code into valid ES5 code (note that in our history section, we mentioned ES5 code can be run in all browsers today). Converting the code into ES5 gives developers a way of seeing and using the features of the latest version of ECMAScript without any problem. Using Babel, we can run all the code samples that are presented in this book.
After you have installed Babel, we can get our hands dirty by seeing our first simple function.
First Function
A Simple Function
Note
It’s not necessary to run the code samples in the Babel world. If you’re using the latest browser and you’re sure that it supports the latest version of ECMAScript, then you can use your browser console to run the code snippets. After all it’s a matter of choice. If you’re running the code, say in Chrome, for example, Listing 2-1 should give you this result:
function () => "Simple Function"
The point to note here is the results might differ in showing the function representation based on where you’re running the code snippets.
We can skip the function keyword to define functions. You can see we have used the => operator to define the function body. Functions created this way are called arrow functions. We use arrow functions throughout the book.
Now that the function is defined, we can execute it to see the result. Oh wait, the function we have created doesn’t have a name. How do we call it?
Note
Functions that don’t have names are called anonymous functions. We will understand the usage of anonymous functions in the functional programming paradigm, when seeing higher order functions in Chapter 3.
A Simple Function with a Name
That’s our equivalent code in ES5. You can sense how it is much easier and more concise to write functions in the latest versions. There are two important points to note in the converted code snippets. We discuss them one after the other.
Strict Mode
In this section we discuss strict mode in JavaScript . We’ll see its benefits and why one should prefer strict mode.
Strict mode has nothing to do with the latest versions, but discussing it here is appropriate. As we have already discussed, strict mode was introduced to JavaScript language with ES5.
Simply put, strict mode is a restricted variant of JavaScript. The same JavaScript code that is running in strict mode can be semantically different from the code, which is not using strict mode. All the code snippets that don’t use strict in their JavaScript files are going to be in nonstrict mode.
In strict mode it’s going to be an error! That’s a good catch for our developers, because global variables are very evil in JavaScript. However, if the same code were run in nonstrict mode, then it wouldn’t have complained about the error.
Now as you can guess, the same code in JavaScript can produce different results whether you’re running in strict or nonstrict mode. Because strict mode is going to be very helpful for us, we will leave Babel to use strict mode while transpiling our ES8 codes.
Note
We can place use stricts in the beginning of a JavaScript file, in which case it’s going to apply its check for the full functions defined in the particular file. Otherwise, you can use strict mode only for specific functions. In that case, strict mode will be applied only to that particular function, leaving other function behaviors in nonstrict mode. For more information on this, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode .
Return Statement Is Optional
Thus here, if you have a function with only a single statement then it implicitly means that it returns the value. What about multiple statement functions? How we are going to create them?
Multiple Statement Functions
Multistatement Function
Run this function, and you will get the same result as before. Here, though, we have used multiple arguments to achieve the same behavior. Apart from that, notice that we have used the let keyword to define our value variable. The let keyword is new to the JavaScript keyword family. It allows you to declare variables that are limited to a particular scope of block, unlike the var keyword, which defines the variable globally to a function regardless of the block in which it is defined.
SimpleFn with var and let Keywords
As you can see from the output, the variable declared via the let keyword is accessible only within the if block, not outside the block. JavaScript throws the error when we access a variable outside the block, whereas the variable declared with var doesn’t act that way. Rather, it declares the variable scope for the whole function. That’s the reason variable b can be accessed outside the if block.
Because block scope is very much needed going forward, we will be using the let keyword for defining variables throughout the book. Now let’s see how to create a function with arguments as the final section.
Function Arguments
Function with Argument
Here we create a function called identity , which takes value as its argument and returns the same. As you can see, creating functions with arguments is the same as in ES5; only the syntax of creating the function is changed.
ES5 Functions Are Valid in ES6 and Above
Before we close this section, we need to make an important point clear. The functions that were written in ES5 are still valid in the latest version(s). It’s just a small matter that newer versions have introduced arrow functions, but that doesn’t replace the old function syntax or anything else. However, we will be using arrow functions throughout this book to showcase the functional programming approach.
Setting Up Our Project
Now that we understand how to create arrow functions, we shift our focus to project setup in this section. We are going to set up our project as a node project and at the end of the section, we will be writing our first functional function.
Initial Setup
- 1.
The first step is to create a directory where our source code is going to be. Create a directory and name it whatever you want.
- 2.
Go into that particular directory and run the following command from your terminal:
- 3.
After running Step 2, you will be asked a set of questions; you can provide the value you want. Once it’s done, it will create a file called package.json in your current directory.
Package.json Contents
Note
The book uses Babel version “babel-preset-es2017-node7.” This specific version might be outdated by the time you read this text. You are free to install the latest version, and everything should work smoothly. However, in the context of the book, we will be using the specified version.
This command downloads the babel package called ES2017; the main aim of this package is to allow the latest ECMAScript code to run on the Node Js platform. The reason is that Node Js, at the time of writing this book, is not fully compatible with the latest features.
Once this command is run, you will be able to see a folder called node_modules created in the directory, which has the babel-preset-es2017 folder.
After Adding devDependencies
Now we are going to put all our functional library code into lib and use functional-playground to explore and understand our functional techniques.
Our First Functional Approach to the Loop Problem
Looping an Array
As we have already discussed in Chapter 1, abstracting the operations into functions is one of the pillars of functional programming. Let’s abstract this operation into function, so that we can reuse it any time we need to rather than repeating ourselves in telling it how to iterate the loop.
forEach Function
Note
For now don’t worry about how this function works. We are going to see how higher order functions work in JavaScript in the next chapter and provide loads of examples.
We will call the forEach in our play.js file. How are we are going to call this function, which resides in a different file?
Gist on Exports
Exporting forEach Function
Gist on Imports
Importing forEach Function
Using the Imported forEach Function
Running the Code Using Babel-Node
Let’s run our play.js file. Because we are using the latest version in our file, we have to use Babel-Node to run our code. Babel-Node is used to transpile our code and run it on Node js. Babel-Node should be installed along with babel-cli.
Note
We will be using this pattern throughout the book. We discuss the problem with an imperative approach and then go ahead and implement our functional techniques and capture them in a function into es8-functional.js. We then use that to play around in the play.js file!
Creating Script in Npm
Adding npm Scripts to package.json
This will run the same as before.
Running the Source Code from Git
Once you check out the branch, you can run the playground file as before.
Summary
In this chapter, we have spent a lot of time learning how to use functions. We have taken advantage of Babel tools for running our code seamlessly in our Node platform. We also created our project as a node project. In our node project, we saw how to use Babel-node to convert the code and run them in a node environment using presets. We also saw how to download the book source code and run it. With all these techniques under our belt, in the next chapter we will be focusing on what higher order functions mean. We will explain the Async/Await features of ES7 in later chapters.