104

I'm using a third-party library that has a function that takes functions as arguments. I'm doing some conditional checks to decide whether or not to add a particular function as a parameter and in some cases I don't want to provide a function. Providing null in that cases throws an error.

I found this code which works, but I don't fully understand what's happening.

compose(__DEV__ ? devTools() : f => f)

Is f => f equivalent to () => {} an empty anonymous function?

Inzamam Malik
  • 3,238
  • 3
  • 29
  • 61
SomethingOn
  • 9,813
  • 17
  • 68
  • 107
  • 3
    It returns an object literal of `f`, according to [MDN](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions#Advanced_Syntax) – Eli Sadoff Dec 20 '16 at 15:47
  • 4
    not empty anonymous, it is identity. – Davin Tryon Dec 20 '16 at 15:49
  • 17
    FWIW, [you can often stick constructs like this into babel](https://babeljs.io/repl/#?babili=false&evaluate=true&lineWrap=false&presets=es2015&experimental=true&loose=false&spec=true&code=f%20%3D%3E%20f) to see what the equivalents in older versions of ECMAscript are. – James Thorpe Dec 20 '16 at 15:49
  • 1
    Possible duplicate of [What's the meaning of "=>" (an arrow formed from equals & greater than) in JavaScript?](http://stackoverflow.com/questions/24900875/whats-the-meaning-of-an-arrow-formed-from-equals-greater-than-in-javas) – Leonid Vasilev Dec 20 '16 at 21:46
  • That answer to http://stackoverflow.com/questions/24900875/whats-the-meaning-of-an-arrow-formed-from-equals-greater-than-in-javas doesn't directly answer this question. I knew f => f was an anonymous function I just didn't understand exactly what it was doing. I think this question is a specific case and the information provided by Felix King about identity functions is unique to this question. – SomethingOn Dec 21 '16 at 13:41
  • *Just as a side question*, in which case could it be usefull? – Mistalis Dec 23 '16 at 10:52
  • Hey Mistalis, in redux the compose function acts like a pipeline, it's a function that takes functions as params and executes them from right to left. The return from each function gets passed to the next function. In my case I had functions that I only wanted to add to compose IF I was in development mode so in the case that I'm not in development mode, null or an empty anonymous function wouldn't work. The function needed to take a param and return that param...hence the function in question. http://redux.js.org/docs/api/compose.html – SomethingOn Dec 23 '16 at 15:22

5 Answers5

191

f => f is the identity function. It simply returns the argument that was passed in.

This function is often used as a default values for transformation processes, since it doesn't perform any transformation.

Is f => f equivalent to () => {} an empty anonymous function?

No. The empty function doesn't return anything. The identity function returns the passed in argument.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • 45
    A+ for providing name, explanation, and a use case, and answering the actual question. – Mulan Dec 20 '16 at 19:32
114

f => f is similar* to function(f){ return f; }

So close, but not quite what you expected.

* - as has been pointed out in comments, there are subtle differences, but for the sake of your question, I don't think they are particularly relevant. They are very relevant in other situations.

Jamiec
  • 133,658
  • 13
  • 134
  • 193
  • 2
    I can think of at least two differences between `f => f` and `function(f) { return f; }` :) – Benjamin Gruenbaum Dec 20 '16 at 22:05
  • 6
    @BenjaminGruenbaum cool, go ahead - even update this answer if you think its relevant. – Jamiec Dec 20 '16 at 22:16
  • 4
    I don't think it's very relevant, just a pedant: `new (f => f)` throws, it has a different `toString` and for some reason I can't quite grok `(f => f).arguments` throws in Chrome but not FF or Edge. – Benjamin Gruenbaum Dec 20 '16 at 22:19
  • 5
    @BenjaminGruenbaum the handling of `this` is also different. (although the difference might not be observable if `this` doesn't appear in the function body... I'm not sure) – Greg Nisbet Dec 20 '16 at 22:30
  • @BenjaminGruenbaum well, according to the current spec, the arrow function itself [must not have its own `caller`/`arguments` properties](https://tc39.es/ecma262/#sec-forbidden-extensions), and [the ones on **Function.prototype**](https://tc39.es/ecma262/#sec-addrestrictedfunctionproperties) (see [CreateIntrinsics](https://tc39.es/ecma262/#sec-createintrinsics)) are defined to throw on access. Possibly things were less precise in 2016? – SamB Mar 01 '23 at 20:50
19

If you want to know what f => f means, the left side is the parameter and the right side is the return value. So for example, f => f*2, is equivalent to:

function(f) { 
  return f * 2; 
}

The code which you describe returns whatever is supplied to it as input.

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Yathi
  • 1,011
  • 1
  • 12
  • 21
9

Others have already mentioned what f => f does, so I'm not going to go deeper into that. I'm just going to explain the rest of the function, because there's a bit of a difference between f => f and __DEV__ ? devTools() : f => f

The ternary operator checks if __DEV__ is a truthy value, and if so, it return function devTools(). otherwise, it return the identity function f => f which does nothing. Put differently: this code enables some development mode functions. Without the remaining code, it's hard to tell what this mode adds, but presumably, it will enable some extra logging information and less obfuscation.

Tr1et
  • 873
  • 11
  • 25
Nzall
  • 3,439
  • 5
  • 29
  • 59
  • `__DEV__ ? devTools() : f => f` does not assign anything to `f`. Did you leave something out from the code example? – Felix Kling Dec 21 '16 at 15:11
  • 2
    It will not return the function, it will return the result of the function – Stephan Bijzitter Dec 21 '16 at 20:31
  • 1
    Your avatar annoys me and disturbs my day. I feel like 90's and my modem lost the connection. Still, +1 anyway, for a good answer. – Konrad Viltersten Dec 22 '16 at 17:36
  • @KonradViltersten You are not the first one to comment on my avatar. You're the first one who doesn't like it though. Most people appreciated the nostalgic factor and the small subversion of expectations it invokes. – Nzall Dec 22 '16 at 18:19
  • 1
    I hope that you got the irony, mate. It was meant as a joke, of course. Obviously, I like it and I find it refreshingly original. – Konrad Viltersten Dec 22 '16 at 19:40
9

Anytime with the similar dilemma, you can use Babel to get the answer.

It returned like this:

"use strict";

(function (f) {
  return f;
});

BTW, => you used is ES6 feature called arrow expression. The other expression of interest

() => {};  // es6

would convert to:

(function () {});

Since arrow function expressions are always anonymous it makes sense if you add the name to the function:

let empty = () => {}; // es6

would convert to

var empty = function empty() {}; 
SNag
  • 17,681
  • 10
  • 54
  • 69
prosti
  • 42,291
  • 14
  • 186
  • 151