> 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 :)
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.
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.
> 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.
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?
If you're writing OO javascript, you often want to use "this" to refer to your object, but various things in js and especially jquery can change the meaning/scoping of "this". So for example, if you have:
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));
}
}
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.
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...
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));
I think that => is going to be used far more than you think. The original scoping rules for javascript have caused all sorts of confusion. The important piece isn't removing function, it's removing .bind(this).
The changes in ES6 go a long way in making modern javascript more intuitive to write.
Yeah, I am really having a hard time seeing what the fat arrow syntax even changes. Everyone keeps saying scope, but the scope is and always has been lexical, right? That isn't changed. All that seems to be changed is what "this" is. So we got a whole new syntax for locking the value of "this". I agree, that does not seem worth it. There are no mental hoops to see that in "self.foo()", "self" was defined 5 lines up.
Let's also note that even though "=>" contains fewer characters than "function", it is arguably more difficult to type, since it requires a jump to the top row of keys for "=", and the shift key for ">".
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...)
If you want to use it now and get full browser support, you can use the TypeScript compiler, which will compile into ES3 or ES5 targets. It also supports ECMAScript 6's classes syntax.
It's pretty neat to use this tech now on production sites and not having to worry about browser support.
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.
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.
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.
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.
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.
[+] [-] graue|12 years ago|reply
> If you’re a JavaScript programmer, chances are you’ve seen (and done) something like this before:
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...
2. http://kangax.github.io/es5-compat-table/es6/#let
[+] [-] robcee|12 years ago|reply
[+] [-] ax|12 years ago|reply
[+] [-] ender7|12 years ago|reply
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_|12 years ago|reply
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.
[+] [-] v413|12 years ago|reply
[+] [-] robcee|12 years ago|reply
[+] [-] tieTYT|12 years ago|reply
In other words, what do I need to read before I can understand this article?
[+] [-] jontas|12 years ago|reply
[+] [-] armandososa|12 years ago|reply
[+] [-] gwwar|12 years ago|reply
[+] [-] EGreg|12 years ago|reply
"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|12 years ago|reply
[+] [-] ebiester|12 years ago|reply
The changes in ES6 go a long way in making modern javascript more intuitive to write.
[+] [-] vectorjohn|12 years ago|reply
[+] [-] Fauntleroy|12 years ago|reply
[+] [-] kurrent|12 years ago|reply
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...
[+] [-] crazygringo|12 years ago|reply
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|12 years ago|reply
[+] [-] janekk|12 years ago|reply
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
[+] [-] robcee|12 years ago|reply
[+] [-] gwwar|12 years ago|reply
I would have preferred a different function keyword that had lexical this binding.
[+] [-] robcee|12 years ago|reply
[+] [-] asaarinen|12 years ago|reply
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|12 years ago|reply
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.
[+] [-] unknown|12 years ago|reply
[deleted]
[+] [-] jmcdonald-ut|12 years ago|reply
[+] [-] gwwar|12 years ago|reply
//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...
[+] [-] Touche|12 years ago|reply
[+] [-] robcee|12 years ago|reply
you can't use spread arguments without the ().
[+] [-] smrtinsert|12 years ago|reply
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.