Fat arrow functions in Javascript
robcee.net
robcee.net
> 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...
e.g.,
function() { var a = 2; // b is visible here if (a == 2) { var b = 3; } }
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.
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.
In other words, what do I need to read before I can understand this article?
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? var myObj = {
foo: 'bar',
baz: function() {
console.log(this.foo); //would give you 'bar', as expected
//but if you have some code that changes the meaning of this, for example:
$('.button').click(function() {
console.log(this.foo); //undefined, since now "this" refers to the scope of the event's callback function
});
//but if you use bind:
$('.button').click((function() {
//now "this" is scoped to refer to the main object
console.log(this.foo); //gives you 'bar'
}).bind(this));
}
}"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.
The changes in ES6 go a long way in making modern javascript more intuitive to write.
What does make me sad is that the old shit isn't going away. And not that it's not going away soon, but that, as far as we can tell, we're going to be teaching people about "this" for the rest of eternity.
I get why Brendan Eich and others are scared of versioning javascript, but I don't think it's tenable to have to keep so many semantically dischordant features of the language around for decades.
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));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.
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...
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...)
It's pretty neat to use this tech now on production sites and not having to worry about browser support.
http://en.wikipedia.org/wiki/TypeScript#ECMAScript_6_support
I would have preferred a different function keyword that had lexical this binding.
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.
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.
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.
//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...
let x = (...args) => { /* some function gunk */ };
So I wonder if this is allowed: let x = ...args => args.join(',')you can't use spread arguments without the ().
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.