DEV Community

Cover image for Functional Programming in JavaScript? Yes, Please.
tiff
tiff

Posted on • Updated on

Functional Programming in JavaScript? Yes, Please.

This post was originally published on my blog

One of the hot topics right now in the web development world is functional programming in the language of the web, JavaScript.

Functional programming encompasses a whole host of mathematical properties and phenomena that is beyond this post, but what I am going to address here is how to write a a few functions with nominal functional programming.

This is going to be a series. I am currently researching these topics as I go along and what I find excites me. I will be digging into these topics, each array method bit by bit. You can find some more of this on Steve Smith’s blog Funky JavaScript.

Important Concept: Higher Order Functions

One of the best and worst parts about JavaScript is that you can pass functions into other functions. This can lead to beautifully expressive code and sometimes bugs.

Why can we do this? Because, like in most functional programming languages 1, functions are values just like any other value in JavaScript.

Take this code:

// Named function or
// function declaration
function double(x) {
  return x * 2;
}

// Anonymous function or
// Function expression
let double = function(x) {
  return x * 2;
}

let cat = double;
// Function call
cat(60);
Enter fullscreen mode Exit fullscreen mode

Here we have named function called double. It takes an argument, x and when you call it, it returns whatever the value of x is that you specify in the function call and returns it.

What’s different about JavaScript is that you can pass it into a variable and call the function from that variable. This is because, well, functions are values.

Higher order functions are good for composition to take smaller functions and make them into bigger functions. More on this in a minute.

Enter .filter()

The .filter() function is an array function that takes a callback that it uses to create a new filtered version of an array.

Take this array of objects:

const animals = [
  { name: Catticus Finch, species: cat },
  { name: Peaches,         species: fish },
  { name: Bobby,          species: dog },
  { name: Lucifer,        species: cat },
  { name: Beatrix,        species: rabbit },
  { name: Cerulean,        species: fish }
];
Enter fullscreen mode Exit fullscreen mode

Say I wanted to filter out all the cats in this array. We could use the trusty for loop:

const cats = [];

for (let i = 0; i < animals.length; i++) {
  if (animals[i].species === cat) {
     cats.push(animals[i]);
  }
}
Enter fullscreen mode Exit fullscreen mode

We are essentially just looping through the array and for every cat the for loop finds, it pushes it into the empty cat array.

Now, we can filter.

Filter accepts a callback and loops through each item in the array and passes it back to the callback function. .filter() expects a boolean and then returns the filtered array.

const cats = animals.filter(function(animal) {
  return animal.species === cats;
});
Enter fullscreen mode Exit fullscreen mode

Here, if the value of the species property in the animals array is a cat it will return the names of those cats in a filtered array.

We could also write an anonymous function and add a filter function inside of it, much like this:

const isCat = function(animal){
  return animal.species === cats;
});

const cats = animals.filter(isCat);
Enter fullscreen mode Exit fullscreen mode

How Cool is This?

Writing small functions allows composition which we can reuse. In the for loop, we are pushing cats into the array but filter handles this natively.

Filter and the callback are composed as they are meshed into each other. Not only is it syntactically pleasing, but it is less lines of code which is always a good thing.

Next Up

Next I want to tackle the .map() function and get back to my Chrome DevTools series.


  1. Though JavaScript isn’t a purely functional programming language. 

Top comments (41)

Collapse
 
bcallaars profile image
Joseph Callaars • Edited

I like this article, it's very clear. Well done! The only comment I have are about the semantics around filter. To "filter" means to "remove", so I would think (or presume) that a filter is an exclusive filter and not an inclusive filter like you use it.

I know this all comes down to semantics, so I'm sure it's a matter of opinion, but when I read filter(isCat) I feel that it shouldn't contain cats.

What is your opinion about this?

Collapse
 
paulraines68 profile image
Paul Raines

Some dictionaries use "remove" in their definition but most define the verb filter as simply passing something through a filter (noun). As a verb, filter is most often followed by either "for" or "out" to make it clear. So even in the 1800's I think a gold miner would say he is using his mesh pan "to filter for gold".

Collapse
 
bcallaars profile image
Joseph Callaars

I accept your explanation, and I fully understand it, albeit I don't agree. When working with computers, a filter means to take impurities out, e.g. a spam filter. So I do understand that this is due to dynamics of a language, but if it was in my code I'd be confused if I saw it used this way.

But again, thanks for your comment :).

Thread Thread
 
zerdnelemo profile image
zerdnelemo

I think that the meaning of "filter" remains the same. And the concept we can apply in programming is filter removes the "impurities", keeping only the desirable data by passing the a parameter (the desirable condition).

Collapse
 
moopet profile image
Ben Sinclair • Edited

This bothers me too.
The callback must return true to include the element in the resultant array, and if we were using filter to remove cats, then we'd need isCat to return false if the element was a cat or to rename it to isNotCat and make it keep returning true. That means either way we can't use that function in both filter and our own code without going insane.

Oh, and in response to your next comment (which for some reason dev.to doesn't let me reply to directly): we have an existing convention of referring to filters on search forms but what they include. If you go to Amazon and search for something, the filters aren't all like "do not include fish food in my results" because that would also be unsuitable for happy life.

Collapse
 
jamsesso profile image
Sam Jesso

I hear you, Joseph. I always had to stop and think about filter until I started thinking of it as a "WHERE" clause in SQL.

When I see filter(isCat) I immediately think of it as WHERE isCat.

Collapse
 
kylegalbraith profile image
Kyle Galbraith

This is well laid out Tiffany. The idea of passing functions around is often a new perspective for folks when first learning Javascript.

Collapse
 
ben profile image
Ben Halpern

Great writeup, Tiffany. Super clear.

Collapse
 
tiffany profile image
tiff

Thanks Ben!

Collapse
 
goshishah profile image
shujaat ali

Thanks for sharing with us :)

Collapse
 
damcosset profile image
Damien Cosset

I find myself writing more and more functional code in Javascript. To me, it's more elegant, readable and easier to test. I'm still learning how to do it properly but, as you mentioned, Javascript not being a purely functional programming, it takes some discipline and patience to stick to it.

Collapse
 
tiffany profile image
tiff

I am really loving how elegant it is. I am still working through learning it, but gosh. Such a better way to go about it. Trying to force JavaScript into OOP may be to its detriment. Still, it is ubiquitous and whatever ECMA decides to do, whichever direction they want to go, I am onboard. Exciting times.

Collapse
 
pamblam profile image
Rob Parham

wat u talkin bout willis? js is oop. literally everything is javascript is an object. even a strings an numbers are natural objects in js. you can do "mystring".length because a string is an object with a length property. you can do (123.123).toFixed() because all numbers are objects with a toFixed method. if you think you have to "force" js into oop then you don't understand the language.

Thread Thread
 
tiffany profile image
tiff

What I actually meant by that is using Classical Inheritance with faux classes and instantiating a new object with things like the new keyword instead of Prototypal Inheritance. Prototypal inheritance is more flexible and is probably the best part of JavaScript's OOP implementation.

Thread Thread
 
pamblam profile image
Rob Parham

Good to hear you say that. I fully agree. Most people don't like the whole prototype thing but I love it.

Thread Thread
 
tiffany profile image
tiff

Coming from doing Java at university, it's taken a while to dig prototypes. I am still working on learning to actually love it. But I understand its power.

Collapse
 
alancampora profile image
Alan Campora • Edited

Something that I think it would be nice to mention, is that the first change you see while you're writing functional programming, is that you're writing less code. But this is just an small consequence of other bigger concept.
The main difference between the for loop and the filter, is that you as a programmer don't have to be aware of how to do the filtering inside the list. You're focus on "what to do" (filter) and not "how to do it" (for loop). This cool concept is there every time you're writing functional programming, because it allows you to be more Declarative and less imperative :D

Collapse
 
vogtis profile image
Vogtis

why in heaven can't you use regular quotes (') so one can copypaste the code and play around? and why don't you use arrows to make code short, like it's 2017?

let cats = animals.filter(a=>a.species==='cats');

Collapse
 
tiffany profile image
tiff

None of what you have said here really matters. I'm making a point, syntax aside. If you want to play around with some code, I suggest you find the code that is syntactically more pleasing to you, as I won't change this. I also don't really need to explain myself.

Collapse
 
damcosset profile image
Damien Cosset

Is this really a constructive comment? The author's code is readable and correct. Using arrow functions doesn't change the point of the article.

Collapse
 
pamblam profile image
Rob Parham

sort of does actually, if we're talking about functional programming you should ideally be using arrow functions as they don't bind this, therefore they're better suited for functional programmng.

Thread Thread
 
damcosset profile image
Damien Cosset

I am not sure that using this in functional programming is recommended. If you don't need to bind this, it means that you need to access the outer this scope right? Therefore, this function is not pure anymore and doesn't solely rely on its arguments. Or am I not understanding something ?

There is also the problem of readability with arrow functions. The syntax is shorter, no doubt, but functions are anonymous. It might not always be useful to trade readability for shorter code.

Thread Thread
 
pamblam profile image
Rob Parham

Exactly. Anything that binds "this" is oop, not functional. Arrow functions do not, so they're better suited for truly functional programming.

Collapse
 
_mravko profile image
Мравко

Hey, first of all thank you for your article. What I have to say might sound a little offensive but I have to say it. Things like the filter method that you mentioned have been present in the programming world for ages. Think of extension methods. LINQ. What I don't understand is how people connect functional programming like it is something so new and powerful, but it is been there for long time and people use it every day. LINQ has a lot of extension methods far more powerful than filter. The thing is that using methods like filter is not even functional programming in my opinion. It is just an extension method on an Array object (C# terminology). Map will also be the same. Functional programming is far more than map and filter. But it is not the silver bullet. It will not solve your problems especially if you are working on complex domain logic. Just think about it. People had the functional style lying around, but history has proven that it is far more better to solve complex domain with Domain Driven Design rather than functional style, that is why they used DDD.

I feel like this hype around FP is cluttering people minds. People start to see OOP like it is a bad thing. Writing pure functions is good, but it will not solve all of your problems. Your code will never be close to the domain logic. It might be closer to the developers. And that is not what you want on big projects.

Read about DDD and OOP and think of how you will solve complex domains using DDD and how will you solve them using FP.

Collapse
 
lluismf profile image
Lluís Josep Martínez

Yes yes and yes! The amount of silly assertions around the FP stuff is just incredible. Loops are bad, classes are bad, conditionals are bad ... even if it makes more sense to write something in an imperative way, the FP approach is by definition better even if it's clumsier and more difficult to read. I'm tired of always seeing the trivial filter, map and reduce stuff, like all of the problems in the real world can be solved with these functions (which are useful of course, but not for everything!!!!!).

Collapse
 
tiffany profile image
tiff • Edited

I understand that FP has been around for a long time and that it is more than filter and map. But all of the intricacies of FP are far beyond the scope of this post.

I don't think OOP is bad at all. I don't think one way is better than another. OOP is still relevant when it comes to large scale systems. I was just excited to learn about these methods. Good points you've made here, though.

Collapse
 
nancyd profile image
Nancy Deschenes

If you want to talk about things that have been around for years, you really should go much further back. Lisp (functional) has been around for a very long time. OOP has been around a long time too, starting as lisp atoms. FP isn't new, but it's gaining popularity.

We're already at the age where everything old is new again with computers, but each iteration brings improvements. The tools to program with OOP and FP have come a long way, and the abstractions we're capable of now are definitely better.

There is a lot more to functional programming than what's in this post, of course, but the essence of passing functions as values is one of its pillars. Another pillar that wasn't covered (you can't cover everything in one post) is that you need your functions to behave in a predictable manner, such that repeated calls with the same parameter will return the same value, no matter how many times you call it, or in what order.

Collapse
 
beecallpaw profile image
Becalpa Thapa

//this code doesn't work
let cats = animals.filter(function(animal) {
return animal.species === ‘cats’;
});
// this does
let cats = animals.filter(function(animal) {
return animal.species === 'cat';
});

Collapse
 
tiffany profile image
tiff

Yeah I see that. Thanks.

Collapse
 
ardennl profile image
Arden de Raaij

Very nice! The whole idea of functional programming in is is very appealing because it really brings some structure to the language. JavaScript has been like the wild west for such a long time, where inheriting a codebase meant rewriting it half of the time because it was so difficult to find what's going on. I feel like functional programming and frameworks really give us a nice way to standardise what we're writing.

Looking forward to the next post!

Collapse
 
oreillyross_50 profile image
Faktor 10

Thanks Tiffany great article. Javascript is a great language for FP, I am loving learning FP with Javascript.

I had one (hopefully constructive) comment, is there a reason you use let as oppose to const? For me const is more intuitive given the FP immutability aspect. Just a thought if the aim is to make code as readable as possible. I believe .filter() returns a new array.

Collapse
 
tiffany profile image
tiff

I thought about using const when doing this but wasn't sure I should. I will change it.

Collapse
 
dansimiyu profile image
dan-simiyu

Great piece Tiffany. I love the fact that JavaScript is multi-paradigm.

Collapse
 
mogery profile image
Gergő Móricz

Hey, I think you missed a couple of commas in the second code block.

Collapse
 
tiffany profile image
tiff

Yep, I see that. Thanks. Will fix it now.

Collapse
 
haraldkampen profile image
Harald Kampen

Please, use namespaces:

const MyNamespace = {};

MyNamespace.isCat = function(animal){
return animal.species === 'cat';
});

Collapse
 
joelnet profile image
JavaScript Joel

There are better ways to organize code than namespaces. With ES6 modules and webpack (recommended), namespaces are unnecessary.

Collapse
 
juni profile image
Junaid Anwar

Nice article, I have a question that why did you define the function twice in the first code block?

Function double(x)
And
Let double = function(x)

Collapse
 
tiffany profile image
tiff • Edited

One is a function declaration:

function double(x)

or named function. The other is a function expression
let double = function(x)

or anonymous function.

I declared each to show how easy it is to reassign a value with an anonymous function.