
Fat arrow functions in Javascript - vbv
http://robcee.net/2013/fat-arrow-functions-in-javascript
======
graue
Did anyone else do a double take reading this?

> _If you’re a JavaScript programmer, chances are you’ve seen (and done)
> something like this before:_
    
    
        var listener = node.addEventListener("click", function(event) {
            let _target = event.target;
            this.handleClick(_target);
        }.bind(this));
    

I had to go look up `let` in JavaScript[1]. It appears to still be a bleeding-
edge feature not widely supported[2] outside of Firefox... not even in Node
with the --harmony flag. I wonder if this is meant to be subtle pro-ES6
propaganda, or the author really takes `let` for granted and doesn't realize
most JS programmers have never seen it :)

1\. [https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Refe...](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Statements/let)

2\. [http://kangax.github.io/es5-compat-
table/es6/#let](http://kangax.github.io/es5-compat-table/es6/#let)

~~~
robcee
I was aware it's pretty modern but honestly didn't think about it much. We use
it heavily in Firefox Devtools code and I much prefer its non-hoisting
properties over var.

~~~
iMark
Out of curiosity, what do you mean by non-hoisting properties? According to
the MDN docs let variables are hoisted, at least to the enclosing block.

~~~
robcee
I usually think of "hoisting" as promoting a var outside of its containing
scope to within the next block.

e.g.,

function() { var a = 2; // b is visible here if (a == 2) { var b = 3; } }

~~~
iMark
Hoisting still occurs within a scope such that, for example, a function
defined at the end of a block can be called at the top.

~~~
robcee
right. The point I was trying to illustrate was that the inner variable
declared with a "var" keyword was visible outside its containing block. If I'd
used "let" there, it would not be.

------
ender7
_First and probably most useful is that they gain the lexical scope of the
environment they’re defined in._

Nit: technically, all Javascript functions are lexically scoped. The fat arrow
permanently binds the value of "this", which is sort of like modifying the
scope, but again not technically because "this" is a special keyword and not a
variable.

~~~
_greim_
> The fat arrow permanently binds the value of "this"

I'm still trying to understand the details here, but my impression is that
()=>{} isn't a shorthand for function(){}.bind(this). The latter creates two
functions, one with an auto-bound "this" and another with a manually-bound
"this". The former creates one function, skipping the step of auto-binding a
new "this" to it. So it just sees the outer "this" via the normal scope chain
(I think). The idea being that JS is doing fewer things in the background and
makes functional programming a little easier on the CPU.

~~~
ax
Each function has its own this binding - the conceptual model for this is that
its an implicit argument to every function call. There is no scope chain
lookup for "this". Although, there is no way to observe any difference between
your understanding of the semantics or the bind semantics (which is a valid
desugarding AFAIK) so the distinction is mostly moot...

------
tieTYT
This article is written for someone who already understands the old issue that
this is fixing (there's nothing wrong with writing it like that). But for
someone like me that doesn't understand when you need to use this `bind()`
stuff and the context your function is in (if I'm even saying that correctly),
what can I read to get a better understanding of what's going on here?

In other words, what do I need to read before I can understand this article?

~~~
armandososa
this is a good start [http://yehudakatz.com/2011/08/11/understanding-
javascript-fu...](http://yehudakatz.com/2011/08/11/understanding-javascript-
function-invocation-and-this/)

~~~
tieTYT
Great link, that really clarified things for me (I think). The OP article uses
this sample as something you can do with fat arrows. "Because the containing
scope closes over the fat arrow function, you can do things like,"

    
    
        let fib = (n) => {
            if (n <= 1) return 1;
            return fib(n - 1) + fib(n - 2};
        }
    

I don't understand what this is showing. Wouldn't this code work the same way
without fat arrows because there's no `this` being used anywhere?

------
EGreg
I am not pleased at seeing language bloat. Look at what happened with C++11.
Languages are supposed to give a common base for developers to read and write
the same code. New developers should be able to get up to speed quickly, and
see the intent of the other developers, which is one of the reasons Linux is
written in C instead of C++.

 _" Look at all that saved typing!"_

Yeah, shockingly there were only a few characters saved. And yet the mental
overhead of a whole new syntax is introduced, which developers can now
encounter in the wild.

 _" The real benefit of course is that you don’t have to go through the mental
hoop-jumping of trying to figure out what scope your function is going to run
in (and more often-than-not, you just wanted it to run inside the current
scope the function is being defined in anyway)."_

The amount of mental hoop-jumping recalling more language features and what
they do outweighs this. I can understand if something is really used all the
time. But when something is already a pattern that's pretty straightforward to
type, do we really need another lexical element, which differs in obscure
semantic details like "you can't override the this variable" and other things?

I would argue that languages which are "easy to learn, tough to master", like
Chess, are best for programming large projects.

~~~
rybosome
I understand your sentiment in general, but disagree in this particular case.
I've been writing JavaScript for years in various projects, companies,
partnerships, etc. If I had a nickel for every time I saw...

    
    
        asyncOperation(_.bind(function(x) { this.x += x; }, this));
    

or...

    
    
        asyncOperation(goog.bind(function(x) { this.x += x; }, this));
    

or...

    
    
        asyncOperation(function(x) { this.x += x; }.bind(this));
    

or...

    
    
        asyncOperation($.proxy(function(x) { this.x += x; }, this));
    

or even...

    
    
        var self = this;
        asyncOperation(function(x) { self.x += x; });
    

...then I'd have a lot of nickels. Binding a function to the current scope is
_insanely_ common - adding syntax specifically for it makes sense. I would
argue that it reduces the cognitive overhead of the language, since rather
than needing to read another method call, examine arguments, etc. I can simply
translate a 2-character symbol into the meaning "outer-context-bound
function". There's a lot more bloat in the above examples than there is in
this:

    
    
        asyncOperation((x) => { this.x += x; });
    

This is like arguing that the '+' operator bloats the language, when we could
all just be using Number(17).plus(Number(43));

~~~
EGreg
Well, in this particular case I agree. If an operation is very commonly used,
and/or it can allow major compiler/interpreter optimizations by doing it at
the language-level instead of a library level, then you should put it into the
language.

But this is not the case for SO MANY constructs. Especially in a language like
PHP, where they've recently added even more stuff that very few people would
care about.

~~~
rybosome
That's fair. If language developers were willing to deprecate more
aggressively, it wouldn't be such a problem...but every hacked-up, shoehorned
feature represents a major investment that must be tended to for years.

------
kurrent
This will be a much needed and welcome addition to ECMA 6.

If you're interested in a bit more of a comprehensive overview, Nicholas Zakas
previously wrote an excellent article on arrow functions :

[http://www.nczonline.net/blog/2013/09/10/understanding-
ecmas...](http://www.nczonline.net/blog/2013/09/10/understanding-
ecmascript-6-arrow-functions/)

------
crazygringo
So let me get this straight... a whole new function syntax is being
introduced, just to replace:

    
    
        var that = this;
        var f = function() {
          return that.x;
        }
    

with:

    
    
        var f = () => {
          return this.x;
        }
    

I mean, that's it? That's the whole benefit? Am I missing something else here?
Please tell me I am.

JavaScript is already tricky enough to keep track of everything having to do
with "this", now they're adding extra complexity to that too by having
multiple types of functions that treat "this" even _more_ differently? (Since
it's not like they're removing the original behavior...)

------
jwoah12
Is this syntax part of ECMAScript 6? I.E. will it eventually be supported by
all browsers?

~~~
robcee
it is part of ES6 and should make it to V8 eventually. Soon, I hope!

~~~
pjmlp
Except the web is much more than V8.

~~~
marijn
So it is. Hence the ECMA6 mention.

~~~
pjmlp
Sure, the problem is getting it to the mobile devices out there.

------
gwwar
While this is pretty cool, I'm not really a fan of this. There is less to
type, but I end up spending more time reading what the code is doing since
there's more than one way to do it. (With optional parens, optional braces,
and special syntax for returning objects in a single line).

I would have preferred a different function keyword that had lexical this
binding.

~~~
robcee
Not sure I agree with you. After using them for a few months, they feel pretty
natural, light-weight and used close to where you define them. There's
actually less thinking required when using a fat-arrow function because you
don't really have to worry about the scope.

~~~
Pxtl
I have to agree.

I code in C#. I often grouse about certain cases where we use characters
instead of words - particularly in boolean logic (I find SQL code with AND and
OR and NOT far more readable than C-ish characters)... and especially since
the => operator is a perversion of comparison... I mean, it feels like a
backwards less-than-or-equal.

But after diving headlong into C#'s various lambda and LINQ features, it's
become quite natural, at least for cases where you're creating a function in-
line as an argument to another call.

If I were coding more Javascript? I'd probably deprecate the function() syntax
with its "this" re-binding misfeature altogether.

------
asaarinen
Frankly the fat arrow syntax adds so little value that it's not worth adding
new syntax to JavaScript, just my humble opinion.

The fat arrow seems to be primarily about easier scoping when using this - so
it's trying to patch the single most broken feature a language ever had.

The existing function syntax is fine, rather just avoid using "this" at all in
your code.

------
doublerebel
This pattern is incredibly useful, once I had it available I started seeing it
constantly. Particularly for binding functions to events while retaining
context -- very common in JavaScript.

Knowing the value of `this` at the _beginning_ of a function makes for much
more readable code. Fat arrow and all the other ES6 features available in
CoffeeScript and Traceur are now too valuable to live without imho.

------
jmcdonald-ut
Is there a reason why the author is referring to them as fat arrow functions
instead of lambdas? I am not trying to be snarky, this is genuine curiosity if
there is something differentiating.

~~~
gwwar
If you recall, a lambda is just an anonymous function which javascript already
has.

//an example of a self-executing anonymous function

(function(x) { return x * x; } (3)); //returns 9

arrow functions are a bit different in that:

* It has Lexical this (normally fixed in usual functions via closure or .bind())

* this cannot be redefined

* arrow functions cannot be used as a constructor

* arrow functions are always anonymous

See also:
[http://wiki.ecmascript.org/doku.php?id=harmony:arrow_functio...](http://wiki.ecmascript.org/doku.php?id=harmony:arrow_function_syntax)

------
Touche
Wouldn't it be:

    
    
        let x = (...args) => { /* some function gunk */ };
    

So I wonder if this is allowed:

    
    
        let x = ...args => args.join(',')

~~~
robcee
SyntaxError: syntax error.

you can't use spread arguments without the ().

------
smrtinsert
Having seen all the coffeescript pushback here already I'm not surprised at
the pushback here now. The truth is, it takes maybe a day to get really
comfortable with using the fat arrow, and after that you wonder why it was any
other way before.

Sometimes I wonder if a lot of the anti-coffeescript people in this forum are
simply Javascript native programmers and don't want any change period. I can't
think of many programming languages that stop changing - seems to be the norm.

