50,39 €
Functional programming is a paradigm for developing software with better performance. It helps you write concise and testable code. To help you take your programming skills to the next level, this comprehensive book will assist you in harnessing the capabilities of functional programming with JavaScript and writing highly maintainable and testable web and server apps using functional JavaScript. This second edition is updated and improved to cover features such as transducers, lenses, prisms and various other concepts to help you write efficient programs. By focusing on functional programming, you’ll not only start to write but also to test pure functions, and reduce side effects. The book also specifically allows you to discover techniques for simplifying code and applying recursion for loopless coding. Gradually, you’ll understand how to achieve immutability, implement design patterns, and work with data types for your application, before going on to learn functional reactive programming to handle complex events in your app. Finally, the book will take you through the design patterns that are relevant to functional programming. By the end of this book, you’ll have developed your JavaScript skills and have gained knowledge of the essential functional programming techniques to program effectively.
Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:
Seitenzahl: 627
Veröffentlichungsjahr: 2020
Copyright © 2020 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
Commissioning Editor:Wilson D'souzaAcquisition Editor:Shweta BairoliyaContent Development Editor:Aamir AhmedSenior Editor: Hayden EdwardsTechnical Editor:Jane DsouzaCopy Editor: Safis EditingProject Coordinator:Manthan PatelProofreader: Safis EditingIndexer:Manju ArasanProduction Designer:Joshua Misquitta
First published: November 2017 Second edition: January 2020
Production reference: 1240120
Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.
ISBN 978-1-83921-306-9
www.packt.com
Packt.com
Subscribe to our online digital library for full access to over 7,000 books and videos, as well as industry leading tools to help you plan your personal development and advance your career. For more information, please visit our website.
Spend less time learning and more time coding with practical eBooks and Videos from over 4,000 industry professionals
Improve your learning with Skill Plans built especially for you
Get a free eBook or video every month
Fully searchable for easy access to vital information
Copy and paste, print, and bookmark content
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.packt.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.
At www.packt.com, you can also read a collection of free technical articles, sign up for a range of free newsletters, and receive exclusive discounts and offers on Packt books and eBooks.
Federico Kereki is an Uruguayan systems engineer, with a master's degree in education, and more than 30 years of experience as a consultant, system developer, university professor, and writer.
He is currently a subject matter expert at Globant, where he gets to use a good mixture of development frameworks, programming tools, and operating systems, such as JavaScript, Node.js, React and Redux, SOA, Containers, and PHP, with both Windows and Linux.
He has taught several computer science courses at Universidad de la República, Universidad ORT Uruguay, and Universidad de la Empresa. He has also written texts for these courses.
He has written several articles—on JavaScript, web development, and open source topics—for magazines such as Linux Journal and LinuxPro Magazine in the United States, Linux+ and Mundo Linux in Europe, and for websites such as Linux.com and IBM Developer Works. He has also written booklets on computer security (Linux in the Time of Malware and SSH: A Modern Lock for Your Server), a book on GWT programming (Essential GWT: Building for the Web with Google Web Toolkit), and another one on JavaScript development (Modern JavaScript Web Development Cookbook).
Federico has given talks on functional programming with JavaScript at public conferences (such as JSCONF 2016 and Development Week Santiago 2019) and has used these techniques to develop internet systems for businesses in Uruguay and abroad.
His current interests tend toward software quality and software engineering—with agile methodologies topmost—while on the practical side, he works with diverse languages, tools, and frameworks, and open source software (FLOSS) wherever possible!
He usually resides, works, and teaches in Uruguay, but this book was fully written while on a project in India, and the revisions for the second edition were finished during a sojourn in Mexico.
Steve Perkins is the author of Hibernate Search by Example. He has been working with Java and JavaScript since the late-1990's, with forays into Scala, Groovy, and Go. Steve lives in Atlanta, GA, with his wife and two children, and is currently a software architect at Banyan Hills Technologies, where he works on a platform for IoT device management and analytics.
When he is not writing code or spending time with family, Steve plays guitar and loses games at bridge and backgammon. You can visit his technical blog at steveperkins.com, and follow him on Twitter at @stevedperkins.
Cristian "Pusher" Bietti is an entrepreneur who is proactive and has a creative attitude to facing challenges in new technologies, with a great hunger to learn more! A senior developer with more than 18 years of experience in software development and software design and trained in a wide variety of technologies, he has participated in big banking projects and small applications for mobile and social networks, including video games.
He has focused on frontend and user experience (UI/UX). He is a subject matter expert at Globant, and he works in the Fintech industry as a technical leader and developer because he loves coding.
If you're interested in becoming an author for Packt, please visit authors.packtpub.com and apply today. We have worked with thousands of developers and tech professionals, just like you, to help them share their insight with the global tech community. You can make a general application, apply for a specific hot topic that we are recruiting an author for, or submit your own idea.
Title Page
Copyright and Credits
Mastering JavaScript Functional Programming Second Edition
Dedication
About Packt
Why subscribe?
Contributors
About the author
About the reviewers
Packt is searching for authors like you
Preface
Who this book is for
What this book covers
To get the most out of this book
Download the example code files
Conventions used
Get in touch
Reviews
Technical Requirements
Becoming Functional - Several Questions
What is functional programming?
Theory versus practice
A different way of thinking
What FP is not
Why use FP?
What we need
What we get
Not all is gold
Is JavaScript functional?
JavaScript as a tool
Going functional with JavaScript
Key features of JavaScript
Functions as first-class objects
Recursion
Closures
Arrow functions
Spread
How do we work with JavaScript?
Using transpilers
Working online
Testing
Summary
Questions
Thinking Functionally - A First Example
Our problem – doing something only once
Solution 1 – hoping for the best!
Solution 2 – using a global flag
Solution 3 – removing the handler
Solution 4 – changing the handler
Solution 5 – disabling the button
Solution 6 – redefining the handler
Solution 7 – using a local flag
A functional solution to our problem
A higher-order solution
Testing the solution manually
Testing the solution automatically
Producing an even better solution
Summary
Questions
Starting Out with Functions - A Core Concept
All about functions
Of lambdas and functions
Arrow functions – the modern way
Returning values
Handling the this value
Working with arguments
One argument or many?
Functions as objects
A React-Redux reducer
An unnecessary mistake
Working with methods
Using functions in FP ways
Injection – sorting it out
Callbacks, promises, and continuations
Continuation passing style
Polyfills
Detecting Ajax
Adding missing functions
Stubbing
Immediate invocation
Summary
Questions 
Behaving Properly - Pure Functions
Pure functions
Referential transparency
Side effects
Usual side effects
Global state
Inner state
Argument mutation
Troublesome functions
Advantages of pure functions
Order of execution
Memoization
Self-documentation
Testing
Impure functions
Avoiding impure functions
Avoiding the usage of state
Injecting impure functions
Is your function pure?
Testing – pure versus impure
Testing pure functions
Testing purified functions
Testing impure functions
Summary
Questions
Programming Declaratively - A Better Style
Transformations
Reducing an array to a value
Summing an array
Calculating an average
Calculating several values at once
Folding left and right
Applying an operation – map
Extracting data from objects
Parsing numbers tacitly
Working with ranges
Emulating map() with reduce()
Dealing with arrays of arrays
Flattening an array
Mapping and flattening – flatMap()
Emulating flat() and flatMap()
More general looping
Logical higher-order functions
Filtering an array
A reduce() example
Emulating filter() with reduce()
Searching an array
A special search case
Emulating find() and findIndex() with reduce()
Higher-level predicates – some, every
Checking negatives – none
Working with async functions
Some strange behaviors
Async-ready looping
Looping over async calls
Mapping async calls
Filtering with async calls
Reducing async calls
Summary
Questions
Producing Functions - Higher-Order Functions
Wrapping functions – keeping behavior
Logging
Logging in a functional way
Taking exceptions into account
Working in a purer way
Timing functions
Memoizing functions
Simple memoization
More complex memoization
Memoization testing
Altering a function's behavior
Doing things once, revisited
Logically negating a function
Inverting the results
Arity changing
Changing functions in other ways
Turning operations into functions
Implementing operations
A handier implementation
Turning functions into promises
Getting a property from an object
Demethodizing – turning methods into functions
Finding the optimum
Summary
Questions
Transforming Functions - Currying and Partial Application
A bit of theory
Currying
Dealing with many parameters
Currying by hand
Currying with bind()
Currying with eval()
Partial application
Partial application with arrow functions
Partial application with eval()
Partial application with closures
Partial currying
Partial currying with bind()
Partial currying with closures
Final thoughts
Parameter order
Being functional
Summary
Questions
Connecting Functions - Pipelining and Composition
Pipelining
Piping in Unix/Linux
Revisiting an example
Creating pipelines
Building pipelines by hand
Using other constructs
Debugging pipelines
Using tee
Tapping into a flow
Using a logging wrapper
Pointfree style
Defining pointfree functions
Converting to pointfree style
Chaining and fluent interfaces
An example of fluent APIs
Chaining method calls
Composing
Some examples of composition
Unary operators
Counting files
Finding unique words
Composing with higher-order functions
Testing composed functions
Transducing
Composing reducers
Generalizing for all reducers
Summary
Questions
Designing Functions - Recursion
Using recursion
Thinking recursively
Decrease and conquer – searching
Decrease and conquer – doing powers
Divide and conquer – the Towers of Hanoi
Divide and conquer – sorting
Dynamic programming – making change
Higher-order functions revisited
Mapping and filtering
Other higher-order functions
Searching and backtracking
The eight queens puzzle
Traversing a tree structure
Recursion techniques
Tail call optimization
Continuation passing style
Trampolines and thunks
Recursion elimination
Summary
Questions
Ensuring Purity - Immutability
Going the straightforward JavaScript way
Mutator functions
Constants
Freezing
Cloning and mutating
Getters and setters
Getting a property
Setting a property by path
Lenses
Working with lenses
Implementing lenses with objects
Implementing lenses with functions
Prisms
Working with prisms
Implementing prisms
Creating persistent data structures
Working with lists
Updating objects
A final caveat
Summary
Questions
Implementing Design Patterns - The Functional Way
Understanding design patterns
Design pattern categories
Do we need design patterns?
Object-oriented design patterns
Facade and adapter
Decorator or wrapper
Strategy, Template, and Command
Observer and reactive programming
Basic concepts and terms
Operators for observables
Detecting multi-clicks
Providing typeahead searches
Other patterns
Functional design patterns
Summary
Questions
Building Better Containers - Functional Data Types
Specifying data types
Signatures for functions 
Other data type options
Building containers 
Extending current data types
Containers and functors
Wrapping a value – a basic container
Enhancing our container – functors
Dealing with missing values with Maybe
Dealing with varying API results
Implementing Prisms
Monads
Adding operations
Handling alternatives – the Either monad
Calling a function – the Try monad
Unexpected monads – promises
Functions as data structures
Binary trees in Haskell
Functions as binary trees
Summary
Questions
Bibliography
Answers to Questions
Chapter 1, Becoming Functional – Several Questions
Chapter 2, Thinking Functionally – a First Example
Chapter 3, Starting Out with Functions – a Core Concept
Chapter 4, Behaving Properly – Pure Functions
Chapter 5, Programming Declaratively – a Better Style
Chapter 6, Producing Functions – Higher-Order Functions
Chapter 7, Transforming Functions – Currying and Partial Application
Chapter 8, Connecting Functions – Pipelining and Composition
Chapter 9, Designing Functions – Recursion
Chapter 10, Ensuring Purity – Immutability
Chapter 11, Implementing Design Patterns – the Functional Way
Chapter 12, Building Better Containers – Functional Data Types
Other Books You May Enjoy
Leave a review - let other readers know what you think
In computer programming, paradigms abound. Some examples include imperative programming, structured (goto-less) programming, object-oriented programming (OOP), aspect-oriented programming, and declarative programming. Lately, there has been renewed interest in a particular paradigm that can arguably be considered to be older than most (if not all) of the cited ones—Functional Programming (FP). FP emphasizes writing functions and connecting them in simple ways to produce a more understandable and more easily tested code. Thus, given the increased complexity of today's web applications, it's logical that a safer, cleaner way of programming would be of interest.
This interest in FP comes hand in hand with the evolution of JavaScript. Despite its somewhat hasty creation (reportedly managed in only 10 days, in 1995, by Brendan Eich at Netscape), today it's a standardized and quickly growing language, with features more advanced than most other similarly popular languages. The ubiquity of the language, which can now be found in browsers, servers, mobile phones, and whatnot, has also impelled interest in better development strategies. Also, even if JavaScript wasn't conceived as a functional language by itself, the fact is that it provides all the features you'd require to work in that fashion, which is another plus.
It must also be said that FP hasn't been generally applied in industry, possibly because it has a certain aura of difficulty, and it is thought to be theoretical rather than practical, even mathematical, and possibly uses vocabulary and concepts that are foreign to developers—for example, functors? Monads? Folding? Category theory? While learning all this theory will certainly be of help, it can also be argued that even with zero knowledge of the previous terms, you can understand the tenets of FP, and see how to apply it in your own programming.
FP is not something that you have to do on your own, without any help. There are many libraries and frameworks that incorporate, in greater or lesser degrees, the concepts of FP. Starting with jQuery (which does include some FP concepts), passing through Underscore and its close relative, Lodash, or other libraries such as Ramda, and getting to more complete web development tools such as React and Redux, Angular, or Elm (a 100% functional language, which compiles into JavaScript), the list of functional aids for your coding is ever growing.
Learning how to use FP can be a worthwhile investment, and even though you may not get to use all of its methods and techniques, just starting to apply some of them will pay dividends in better code. You need not try to apply all of FP from the start, and you need not try to abandon every non-functional feature in the language either. JavaScript assuredly has some bad features, but it also has several very good and powerful ones. The idea is not to throw away everything you've learned and use and adopt a 100% functional way; rather, the guiding idea is evolution, not revolution. In that sense, it can be said that what we'll be doing is not FP, but rather Sorta Functional Programming (SFP), aiming for a fusion of paradigms.
A final comment about the style of the code in this book—it is quite true that there are several very good libraries that provide you with FP tools: Underscore, Lodash, Ramda, and more are counted among them. However, I preferred to eschew their usage, because I wanted to show how things really work. It's easy to apply a given function from some package or other, but by coding everything out (a vanilla FP, if you wish), it's my belief that you get to understand things more deeply. Also, as I will comment in some places, because of the power and clarity of arrow functions and other features, the pure JavaScript versions can be even simpler to understand!
This book is geared toward programmers with a good working knowledge of JavaScript, working either on the client side (browsers) or the server side (Node.js), who are interested in applying techniques to be able to write better, testable, understandable, and maintainable code. Some background in computer science (including, for example, data structures) and good programming practices will also come in handy.
In this book, we'll cover FP in a practical way; though, at times, we will mention some theoretical points:
Chapter 1, Becoming Functional – Several Questions, discusses FP, gives reasons for its usage, and lists the tools that you'll need to take advantage of the rest of the book.
Chapter 2, Thinking Functionally – A First Example, will provide the first example of FP by considering a common web-related problem and going over several solutions, to finally center on a functional solution.
Chapter 3, Starting Out with Functions – A Core Concept, will go over the central concept of FP, that is, functions, and the different options available in JavaScript.
Chapter 4, Behaving Properly – Pure Functions, will consider the concept of purity and pure functions, and demonstrate how it leads to simpler coding and easier testing.
Chapter 5, Programming Declaratively – A Better Style, will use simple data structures to show how to produce results that work not in an imperative way, but in a declarative fashion.
Chapter 6, Producing Functions – Higher-Order Functions, will deal with higher-order functions, which receive other functions as parameters and produce new functions as results.
Chapter 7, Transforming Functions – Currying and Partial Application, will explore some methods for producing new and specialized functions fromearlierones.
Chapter 8, Connecting Functions – Pipelining and Composition, will show the key concepts regarding how to build new functions by joining previously defined ones.
Chapter 9, Designing Functions – Recursion,will look at how a key concept in FP, recursion, can be applied to designing algorithms and functions.
Chapter 10, Ensuring Purity – Immutability, will present some tools that can help you to work in a pure fashion by providing immutable objects and data structures.
Chapter 11, Implementing Design Patterns – The Functional Way, will show how several popular OOP design patterns are implemented (or not needed!) when you program in FP ways.
Chapter 12, Building Better Containers – Functional Data Types, will explore some more high-level functional patterns, introducing types, containers, functors, monads, and several other more advanced FP concepts.
I have tried to keep the examples in this book simple and down to earth because I want to focus on the functional aspects and not on the intricacies of this or that problem. Some programming texts are geared toward learning, say, a given framework, and then work on a given problem, showing how to fully work it out with the chosen tools. (In fact, at the very beginning of planning for this book, I entertained the idea of developing an application that would use all the FP things I had in mind, but there was no way to fit all of that within a single project. Exaggerating a bit, I felt like an MD trying to find a patient on whom to apply all of his medical knowledge and treatments!) So, I have opted to show plenty of individual techniques, which can be used in multiple situations. Rather than building a house, I want to show you how to put the bricks together, how to wire things up, and so on, so that you will be able to apply whatever you need, as you see fit.
To understand the concepts and code in this book, you don't need much more than a JavaScript environment and a text editor. To be honest, I even developed some of the examples working fully online, with tools such as JSFiddle (athttps://jsfiddle.net/) and the like, and absolutely nothing else.
In this book, we'll be using ES2019, Node 13, and the code will run on any OS such as Linux, Mac OSX, or Windows; please do check the Technical Requirements section, for some other tools we'll also work with.
Finally, you will need some experience with the latest version of JavaScript, because it includes several features that can help you write more concise and compact code. We will frequently include pointers to online documentation, such as the documentation available on the Mozilla Development Network (MDM) athttps://developer.mozilla.org/, to help you get more in-depth knowledge.
You can download the example code files for this book from your account at www.packt.com. If you purchased this book elsewhere, you can visit www.packtpub.com/support and register to have the files emailed directly to you.
You can download the code files by following these steps:
Log in or register at
www.packt.com
.
Select the
Support
tab.
Click on
Code Downloads
.
Enter the name of the book in the
Search
box and follow the onscreen instructions.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR/7-Zip for Windows
Zipeg/iZip/UnRarX for Mac
7-Zip/PeaZip for Linux
The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Mastering-JavaScript-Functional-Programming-2nd-Edition-. In case there's an update to the code, it will be updated on the existing GitHub repository.
We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
Feedback from our readers is always welcome.
General feedback: If you have questions about any aspect of this book, mention the book title in the subject of your message and email us at [email protected].
Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packtpub.com/support/errata, selecting your book, clicking on the Errata Submission Form link, and entering the details.
Piracy: If you come across any illegal copies of our works in any form on the internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.
If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.
Please leave a review. Once you have read and used this book, why not leave a review on the site that you purchased it from? Potential readers can then see and use your unbiased opinion to make purchase decisions, we at Packt can understand what you think about our products, and our authors can see your feedback on their book. Thank you!
For more information about Packt, please visit packt.com.
To develop and test the code in this book, I used several versions of commonly available software, including browsers and Node.js, as well as some other packages.
For this second edition, my main machine runs the Tumbleweed rolling release of OpenSUSE Linux, from https://www.opensuse.org/#Tumbleweed, currently including kernel 5.3.5. (The rolling term implies that the software is updated on a continuous basis, to keep getting the latest versions of all packages.) I've also tested portions of the code of this book on different Windows 7 and Windows 10 machines.
As to browsers, I usually work with Chrome, from https://www.google.com/chrome/browser/, and at the current time, I'm up to version 78. I also use Firefox, from https://www.mozilla.org/en-US/firefox/, and I got version 72 in my machine. I have also run code using the online JSFiddle environment, at https://jsfiddle.net/.
On the server side, I use Node.js, from https://nodejs.org/, currently at version 13.6.
For transpilation, I used Babel, from https://babeljs.io/: the current version of the babel-cli package is 7.7.7.
For testing, I went with Jasmine, from https://jasmine.github.io/, and the latest version in my machine is 3.5.0.
Finally, for code formatting, I used Prettier, from https://prettier.io/. You can either install it locally, or run it online at https://prettier.io/playground/; the version I have is 1.19.1.
The JavaScript world is quite dynamic, and it's a safe bet that by the time you get to read this book, all the software listed above will have been updated several times. Every single piece of software I used when I wrote the 1st edition of this book, received several updates over time. However, given the standardization of JavaScript, and the high importance of back compatibility, you shouldn't have problems with other versions.
Functional programming (or FP) has been around since the earliest days of computing, and is going through a sort of revival because of its increased use with several frameworks and libraries, most particularly in JavaScript (JS). In this chapter, we shall do the following:
Introduce some concepts of FP to give a small taste of what it means.
Show the benefits (and problems) implied by the usage of FP and why we should use it.
Start thinking about why JavaScript can be considered an appropriate language for FP.
Go over the language features and tools that you should be aware of in order to fully take advantage of everything in this book.
By the end of this chapter, you'll have the basic tools that we'll be using in the rest of the book, so let's get started by learning about functional programming.
If you go back in computer history, you'll find that the second oldest programming language still in use, Lisp, is based on FP. Since then, there have been many more functional languages, and FP has been applied more widely. But even so, if you ask people what FP is, you'll probably get two widely dissimilar answers.
Depending on whom you ask, you'll either learn that it's a modern, advanced, enlightened approach to programming that leaves every other paradigm behind or that it's mainly a theoretical thing, with more complications than benefits, practically impossible to implement in the real world. And, as usual, the real answer is not in the extremes, but somewhere in between. Let's start by looking at the theory versus practice and see how we plan to use FP.
In this book, we won't be going about FP in a theoretical way. Instead, our point is to show you how some of its techniques and tenets can be successfully applied for common, everyday JavaScript programming. But—and this is important—we won't be going about this in a dogmatic fashion, but in a very practical way. We won't dismiss useful JavaScript constructs simply because they don't happen to fulfill the academic expectations of FP. Similarly, we won't avoid practical JavaScript features just to fit the FP paradigm. In fact, we could almost say that we'll be doing Sorta Functional Programming (SFP) because our code will be a mixture of FP features, more classical imperative ones, and object-oriented programming (OOP).
Be careful, though: what we just said doesn't mean that we'll be leaving all the theory by the side. We'll be picky, and just touch the main theoretical points, learn some vocabulary and definitions, and explain core FP concepts, but we'll always be keeping in sight the idea of producing actual, useful JavaScript code, rather than trying to meet some mystical, dogmatic FP criteria.
OOP has been a way to solve the inherent complexity of writing large programs and systems, and developing clean, extensible, scalable application architectures; however, because of the scale of today's web applications, the complexity of all codebases is continuously growing. Also, the newer features of JavaScript make it possible to develop applications that wouldn't even have been possible just a few years ago; think of mobile (hybrid) apps that are made with Ionic, Apache Cordova, or React Native or desktop apps that are made with Electron or NW.js, for example. JavaScript has also migrated to the backend with Node.js, so today, the scope of usage for the language has grown in a serious way that deals with all the added complexity of modern designs.
FP is a different way of writing programs, and can sometimes be difficult to learn. In most languages, programming is done in an imperative fashion: a program is a sequence of statements, executed in a prescribed fashion, and the desired result is achieved by creating objects and manipulating them, which usually means modifying the objects themselves. FP is based on producing the desired result by evaluating expressions built out of functions that are composed together. In FP, it's common to pass functions around (such as passing parameters to other functions or returning functions as the result of a calculation), to not use loops (opting for recursion instead), and to skip side effects (such as modifying objects or global variables).
In other words, FP focuses on what should be done, rather than on how. Instead of worrying about loops or arrays, you work at a higher level, considering what you need to be done. After becoming accustomed to this style, you'll find that your code becomes simpler, shorter, and more elegant, and can be easily tested and debugged. However, don't fall into the trap of considering FP as the goal! Think of FP only as a means to an end, as with all software tools. Functional code isn't good just for being functional, and writing bad code is just as possible with FP as with any other technique!
Since we have been saying some things about what FP is, let's also clear up some common misconceptions, and look at what FP is not:
FP isn't just an academic ivory tower thing
: It is true that the
lambda calculus
upon which it is based was developed by Alonzo Church in 1936 as a tool to prove an important result in theoretical computer science (which preceded modern computer languages by more than 20 years!); however, FP languages are being used today for all kinds of systems.
FP isn't the opposite of object-oriented programming (OOP)
: It isn't a case of choosing declarative or imperative ways of programming. You can mix and match as best suits you, and we'll be doing this throughout this book, bringing together the best of all worlds.
FP isn't overly complex to learn
: Some of the FP languages are rather different from JavaScript, but the differences are mostly syntactic. Once you learn the basic concepts, you'll see that you can get the same results in JavaScript as with FP languages.
It may also be relevant to mention that several modern frameworks, such as the React and Redux combination, include FP ideas.
For example, in React, it's said that the view (whatever the user gets to see at a given moment) is a function of the current state. You use a function to compute what HTML and CSS must be produced at each moment, thinking in a black-box fashion.
Similarly, in Redux you have the concept of actions that are processed by reducers. An action provides some data, and a reducer is a function that produces the new state for the application in a functional way out of the current state and the provided data.
So, both because of the theoretical advantages (we'll be getting to those in the following section) and the practical ones (such as getting to use the latest frameworks and libraries), it makes sense to consider FP coding. Let's get on with it.
Throughout the years, there have been many programming styles and fads. However, FP has proven quite resilient and is of great interest today. Why would you want to use FP? The question should rather first be, what do you want to get? and only then, does FP get you that? Let's answer these important questions in the following sections.
We can certainly agree that the following list of concerns is universal. Our code should have the following qualities:
Modular
: The functionality of your program should be divided into independent modules, each of which contains what it needs to perform one aspect of the program's functionality. Changes in a module or function shouldn't affect the rest of the code.
Understandable
: A reader of your program should be able to discern its components, their functions, and their relationships without undue effort. This is closely linked with the
maintainability
of the code; your code will have to be maintained at some time in the future, whether to be changed or to have new functionality added.
Testable
:
Unit tests
try out small parts of your program, verifying their behavior independently of the rest of the code. Your programming style should favor writing code that simplifies the job of writing unit tests. Unit tests are also like documentation in that they can help readers understand what the code is supposed to do.
Extensible
: It's a fact that your program will someday require maintenance, possibly to add new functionality. Those changes should impact the structure and data flow of the original code only minimally (if at all). Small changes shouldn't imply large, serious refactoring of your code.
Reusable
:
Code reuse
has the goal of saving resources, time, and money, and reducing redundancy by taking advantage of previously written code. There are some characteristics that help this goal, such as
modularity
(which we already mentioned),
high cohesion
(all the pieces in a module belong together),
low coupling
(modules are independent of each other),
separation of concerns
(the parts of a program should overlap in functionality as little as possible), and
information hiding
(internal changes in a module shouldn't affect the rest of the system).
So does FP give you the five characteristics we just listed in the previous section?
In FP, the goal is to write separate independent functions that are joined together to produce the final results.
Programs that are written in a functional style usually tend to be cleaner, shorter, and easier to understand.
Functions can be tested on their own, and FP code has advantages in achieving this.
You can reuse functions in other programs because they stand on their own, not depending on the rest of the system. Most functional programs share common functions, several of which we'll be considering in this book.
Functional code is free from side effects, which means you can understand the objective of a function by studying it without having to consider the rest of the program.
Finally, once you get used to the FP style of programming, code becomes more understandable and easier to extend. So it seems that all five characteristics can be achieved with FP!
However, let's strive for a bit of balance. Using FP isn't a silver bullet that will automagically make your code better. Some FP solutions are actually tricky, and there are developers who greatly enjoy writing code and then asking, what does this do? If you aren't careful, your code may become write-only and practically impossible to maintain; there goes understandable, extensible, and reusable out the door!
Another disadvantage is that you may find it harder to find FP-savvy developers. (Quick question: how many functional programmers sought job ads have you ever seen?) The vast majority of today's web code is written in imperative, non-functional ways, and most coders are used to that way of working. For some, having to switch gears and start writing programs in a different way may prove an unpassable barrier.
Finally, if you try to go fully functional, you may find yourself at odds with JavaScript, and simple tasks may become hard to do. As we said at the beginning, we'll opt for sorta FP, so we won't be drastically rejecting any language features that aren't 100% functional. After all, we want to use FP to simplify our coding, not to make it more complex!
So, while I'll strive to show you the advantages of going functional in your code, as with any change, there will always be some difficulties. However, I'm fully convinced that you'll be able to surmount them and that your organization will develop better code by applying FP. Dare to change! So, given that you accept that FP may apply to your own problems, let's now consider the other question, can we use JavaScript in a functional way and is it appropriate?
At about this time, there is another important question that you should be asking: Is JavaScript a functional language? Usually, when thinking about FP, the list of languages that are mentioned does not include JavaScript, but does include less common options, such as Clojure, Erlang, Haskell, and Scala; however, there is no precise definition for FP languages or a precise set of features that such languages should include. The main point is that you can consider a language to be functional if it supports the common programming style associated with FP. Let's start by learning about why we would want to use JavaScript at all and how the language has evolved to its current version, and then see some of the key features that we'll be using to work in a functional way.
What is JavaScript? If you consider popularity indices, such as the ones at www.tiobe.com/tiobe-index/ or http://pypl.github.io/PYPL.html, you'll find that JavaScript is consistently in the top ten most popular languages. From a more academic point of view, the language is sort of a mixture, borrowing features from several different languages. Several libraries helped the growth of the language by providing features that weren't so easily available, such as classes and inheritance (today's version of the language does support classes, but that was not the case not too long ago), that otherwise had to be achieved by doing someprototypetricks.
JavaScript has grown to be incredibly powerful. But, as with all power tools, it gives you a way to not only produce great solutions, but also to do great harm. FP could be considered as a way to reduce or leave aside some of the worst parts of the language and focus on working in a safer, better way; however, due to the immense amount of existing JavaScript code, you cannot expect it to facilitate large reworkings of the language that would cause most sites to fail. You must learn to live with the good and the bad, and simply avoid the latter parts.
In addition, the language has a broad variety of available libraries that complete or extend the language in many ways. In this book, we'll be focusing on using JavaScript on its own, but we will make references to existing, available code.
If we ask whether JavaScript is actually functional, the answer will be, once again, sorta. It can be seen as functional because of several features, such as first-class functions, anonymous functions, recursion, and closures—we'll get back to this later. On the other hand, it also has plenty of non-FP aspects, such as side effects (impurity), mutable objects, and practical limits to recursion. So, when programming in a functional way, we'll be taking advantage of all the relevant, appropriate language features, and we'll try to minimize the problems caused by the more conventional parts of the language. In this sense, JavaScript will or won't be functional, depending on your programming style!
If you want to use FP, you should decide which language to use; however, opting for fully functional languages may not be so wise. Today, developing code isn't as simple as just using a language; you will surely require frameworks, libraries, and other sundry tools. If we can take advantage of all the provided tools but at the same time introduce FP ways of working in our code, we'll be getting the best of both worlds, never mind whether JavaScript is functional!
JavaScript has evolved through the years, and the version we'll be using is (informally) called JS10, and (formally) ECMAScript 2019, usually shortened to ES2019 or ES10; this version was finalized in June 2019. The previous versions were as follows:
ECMAScript 1, June 1997
ECMAScript 2, June 1998, which was basically the same as the previous version
ECMAScript 3, December 1999, with several new functionalities
ECMAScript 5, December 2009 (and no, there never was an ECMAScript 4, because it was abandoned)
ECMAScript 5.1, June 2011
ECMAScript 6 (or ES6; later renamed ES2015), June 2015
ECMAScript 7 (also ES7,
or ES2016), June 2016
ECMAScript 8 (ES8 or ES2017), June 2017
ECMAScript 9 (ES9 or ES2018),
June 2018
You can read the standard language specification at www.ecma-international.org/ecma-262/7.0/. Whenever we refer to JavaScript in the text without further specification, ES10 (ES2019) is what is being referred to; however, in terms of the language features that are used in the book, if you were just to use ES2015, then you'd mostly have no problems with this book.
No browsers fully implement ES10; most provide an older version, JavaScript 5 (from 2009), with an (always growing) smattering of features from ES6 up to ES10. This will prove to be a problem, but fortunately, a solvable one; we'll get to this shortly. We'll be using ES10 throughout the book.
As we are going to work with JavaScript, let's start by considering its most important features that pertain to our FP goals.
JavaScript isn't a purely functional language, but it has all the features that we need for it to work as if it were. The main features of the language that we will be using are as follows:
Functions as first-class objects
Recursion
Arrow functions
Closures
Spread
Let's see some examples of each one and find out why they will be useful to us. Keep in mind, though, that there are more features of JavaScript that we will be using; the upcoming sections just highlight the most important features in terms of what we will be using for FP.
This is all well and good, but as we mentioned before, it so happens that the JavaScript version available almost everywhere isn't ES10, but rather the earlier JS5. An exception to this is Node.js. It is based on Chrome's v8 high-performance JavaScript engine, which already has several ES10 features available. Nonetheless, as of today, ES10 coverage isn't 100% complete, and there are features that you will miss. (Check out https://nodejs.org/en/docs/es6/ for more on Node.js and v8.) This will surely change in the future, as Internet Explorer will fade away, and the newest Microsoft's browser will share Chrome's engine, but for the time being, we must still deal with older, less powerful engines.
So what can you do if you want to code using the latest version, but the available one is an earlier, poorer one? Or what happens if most of your users are using older browsers, which don't support the fancy features you're keen on using? Let's see some solutions for this.
In order to get out of this availability and compatibility problem, there are a couple of transpilers
