Swizec Teller - a geek with a hatswizec.com

Senior Mindset Book

Get promoted, earn a bigger salary, work for top companies

Senior Engineer Mindset cover
Learn more

    JavaScript's native map reduce and filter are wrong

    Last week I saw a tweet by @jhartikainen that made my heart skip a beat! He totally raped the definition of a one liner and made something that can be beautiful only to a giant functional programming nerd.

    The gist that he posted looks like this:

    //Is this abuse of array functions? :D
    "20000001"
      .split("")
      .reverse()
      .join("")
      .match(/\d{3}|\d+$/g)
      .map(function (s) {
        return s.split("").reverse().join("")
      })
      .reverse()
      .join(" ")
    //produces "20 000 001"
    

    Now this might just look like so much brain sputtering madness to you, but it's actually displaying something very awesome about one of my favourite programming languages -- native implementations of map, reduce and so on.

    IMG_2307

    tl;dr --> JavaScript is starting to mix functional and objective programming in a bad bad way

    I'm not exactly certain when JavaScript got native implementations of these as I've been using libraries like underscore.js for a while now to achieve this exact same thing. Actually wikipedia tells me this has been added in version 1.6 way back in November 2005. Six years ago and I didn't know a thing about it.

    That's just sad. Why don't more tutorials online talk about these features? How are people supposed to learn how awesome JavaScript is when most of the community works only with a very small subset of the language?

    Some further searching tells me that the version of JavaScript most browsers currently support is 1.5 and since ECMAScript version 5, which is comparable to JavaScript 1.8, was only standardised in ... December 2009, the browsers are quickly trying to pick up slack and get up to speed with that ...

    This makes me sad, I almost don't feel like continuing this post ... luckily though, Node.js is pretty good with the latest ECMAScript support so there's still hope.

    What's wrong

    Considering the horror show I just described, writing the rest of this post leaves a bad taste in my mouth, but I think the way JavaScript natively implements some features of functional programming is wrong.

    The way map, reduce, filter and others are implemented in JavaScript is that they are methods of the Array class. And you call them as such:

    ;[0, 1, 2].map(function (i) {
      return i + 1
    }) // adds 1 to every member
    ;[0, 1, 2].reduce(function (a, b) {
      return a + b
    }) // sums members
    ;[0, 1, 2].filter(function (i) {
      return i > 0
    }) // removes members smaller than 1
    

    As you can see all of these functions are a way to call a certain function on every member of the array. Nothing too special here, anyone who's ever even sniffed at functional programming should understand how these three functions work.

    But because JavaScript is a language that is both functional and objective in its design, this code suddenly becomes very ambiguous to read.

    On one hand, you're calling functions that are the epitome of functional programming. Obviously there are no side-effects and a copy of the array is returned, leaving the original intact. Immutable data structures and all that functional shebang.

    But on the other hand, you're calling these on an array, as the array's methods. Obviously these functions belong to the Array and are therefore executed in place and the array's state is changed.

    Reading the syntax and knowing the basics of both objective and functional programming, both those opinions look like they should be true. Shouldn't they?

    Turns out, in this case, JavaScript returns a copy of the array and nothing at all happens to the original array. As we can demonstrate with the following quick test in the node.js console:

    Merrick:~ Swizec$ node
    > var a = [1,2,3];
    > var b = a.map(function (i) { return i+1; });
    > a
    [ 1, 2, 3 ]
    > b
    [ 2, 3, 4 ]
    > a.map(function (i) { return i+1; });
    [ 2, 3, 4 ]
    > a
    [ 1, 2, 3 ]
    

    So it would seem that what we have here is a case of functional programming, behaving as functional programming, neatly packaged into an objective syntax.

    Which I guess wouldn't actually be that bad were it consistent.

    Other functions used in this exact same way usually change the array's state. Both sort and reverse return the new array ... but also change the original array's ordering. Similarly every other function on the array ranging from shift and pop to _splice _change the state of the array they are being called on and return ... something (it depends on the particular function).

    This means that reading JavaScript you are faced with the fact that functions called on objects are sometimes performing actions on the copy of the object and sometimes on the object.

    That's just confusing and bloody horrible from a language design standpoint don't you think?

    Why couldn't they just create new global functions for these awesome functional programming concepts ... I mean, the whole idea there is that functions get parameters and only parameters, functions in functional languages are supposed to be context independent. But here you have context dependent functional functions ... it's just a mess.

    Is JavaScript fast becoming like PHP with its confused standard library? Or is it just going through a little identity crysis?

    Published on June 29th, 2011 in Uncategorized

    Did you enjoy this article?

    Continue reading about JavaScript's native map reduce and filter are wrong

    Semantically similar articles hand-picked by GPT-4

    Senior Mindset Book

    Get promoted, earn a bigger salary, work for top companies

    Learn more

    Have a burning question that you think I can answer? Hit me up on twitter and I'll do my best.

    Who am I and who do I help? I'm Swizec Teller and I turn coders into engineers with "Raw and honest from the heart!" writing. No bullshit. Real insights into the career and skills of a modern software engineer.

    Want to become a true senior engineer? Take ownership, have autonomy, and be a force multiplier on your team. The Senior Engineer Mindset ebook can help 👉 swizec.com/senior-mindset. These are the shifts in mindset that unlocked my career.

    Curious about Serverless and the modern backend? Check out Serverless Handbook, for frontend engineers 👉 ServerlessHandbook.dev

    Want to Stop copy pasting D3 examples and create data visualizations of your own? Learn how to build scalable dataviz React components your whole team can understand with React for Data Visualization

    Want to get my best emails on JavaScript, React, Serverless, Fullstack Web, or Indie Hacking? Check out swizec.com/collections

    Did someone amazing share this letter with you? Wonderful! You can sign up for my weekly letters for software engineers on their path to greatness, here: swizec.com/blog

    Want to brush up on your modern JavaScript syntax? Check out my interactive cheatsheet: es6cheatsheet.com

    By the way, just in case no one has told you it yet today: I love and appreciate you for who you are ❤️

    Created by Swizec with ❤️