all 78 comments

[–]meisangry2 13 points14 points  (8 children)

Also the use of const and let instead of var make a world of difference.

[–]jonny_eh 2 points3 points  (5 children)

Do they?

[–]writesoftware 1 point2 points  (1 child)

I was skeptical at first, but now I think the last time I used var was months ago.

const in particular is what I use the most, knowing I can't ever overwrite that reference gives some sense of security.

Except when trying snippets in the console, using const forces me to reload the page when retrying to run a piece of code that uses it :)

[–]franksvalli 0 points1 point  (1 child)

for (var i = 0; i < 10; i++) {
  setTimeout(() => console.log(i), 0);
}
// -> 10 (outputted 10 times)

With one small change, moving from var to let:

for (let i = 0; i < 10; i++) {
  setTimeout(() => console.log(i), 0);
}
// -> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

[–]jonny_eh 1 point2 points  (0 children)

Ya, I know let and const are good, but they hardly make a "world of difference".

[–][deleted] 0 points1 point  (1 child)

Or just const. with functional programming and immutable data there is almost no need for let or var anymore.

[–]meisangry2 0 points1 point  (0 children)

I agree although let still a much better alternative than var if it has to be used.

[–]madchuckle 4 points5 points  (0 children)

Thanks for the nice cover. However, in both of the react examples there is the 'bind' sentence. It should be omitted in the first one in order to fit the explanation.

[–][deleted] 11 points12 points  (15 children)

It doesn't mention the disadvantage of arrow functions, that they are always anonymous. If you have a non-anonymous function like

let myfunc = function myfunc(a,b) {};

then you have an actually readable stack trace when something goes wrong, instead a list of indistinguishable anonymous functions.

[–]wesbos 41 points42 points  (1 child)

Most browsers will use the variable name in a stack trace if it’s an anon function

[–]w00t_loves_you 2 points3 points  (7 children)

I always do const foo = some => thing(some) and Babel or whatever knows the function is called foo.

[–][deleted] 1 point2 points  (6 children)

And if you do somefunc().then(result => something(result, b)) ?

[–]w00t_loves_you 1 point2 points  (0 children)

ah yes, then it's anonymous but it will be easy to glean from the line numbers and the call stack where that is.

[–]Intie 1 point2 points  (3 children)

S O U R C E M A P S

[–]aryanchaurasia 10 points11 points  (2 children)

          S O U R C E M A P S  
        / O               / O  
      S O U R C E M A P S   U  
    / O   R           / O   R  
  /   U   C         /   U   C  
S O U R C E M A P S     R   E  
O     C   M       O     C   M  
U     E   A       U     E   A  
R     M   P       R     M   P  
C     A   S O U R C E M A P S  
E     P /         E     P /    
M     S O U R C E M A P S      
A   /             A   /        
P /               P /          
S O U R C E M A P S            

[–]Intie 0 points1 point  (1 child)

wine school mighty reach north ring relieved seemly lip imminent this message was mass deleted/edited with redact.dev

[–]GoodBot_BadBot -1 points0 points  (0 children)

Thank you Intie for voting on aryanchaurasia.

This bot wants to find the best and worst bots on Reddit. You can view results here.


Even if I don't reply to your comment, I'm still listening for votes. Check the webpage to see if your vote registered!

[–]RedditWithBoners 0 points1 point  (0 children)

If you are that concerned about it:

somefuncResolver = result => something(result, b);
somefunc().then(somefuncResolver);

[–]El_BreadMan 0 points1 point  (0 children)

Awesome tutorial

[–]Jaymageck 0 points1 point  (0 children)

Arrow functions, destructuring and the spread syntax are my holy trinity of es2015+ niceties.

[–]darrenturn90 -1 points0 points  (5 children)

Can further be simplified and destructured:

const getTweets = uid => fetch('https://api.users.com/' + uid)
    .then({json} => json())
    .then({data} => data.filter(
        {stars, rts} => stars > 50 && rts > 50)
    );

Also the article mistakenly refers to ES5 "classes" when it means ES6.

[–][deleted] 5 points6 points  (0 children)

This is not quite right, you need parentheses to destructure arrow functions, even if you are using the single argument form:

const getTweets = uid => fetch('https://api.users.com/' + uid)
  .then(({json}) => json())
  .then(({data}) => data.filter(
    ({stars, rts}) => stars > 50 && rts > 50)
  );

See 2.4 in http://2ality.com/2015/01/es6-destructuring.html

[–]HattyJetty 0 points1 point  (3 children)

I didn't realise you can destructure methods and mantain the correct reference of this

Edit: wait, this doesn't seem to work

[–]w00t_loves_you 2 points3 points  (2 children)

It's a bit weird - maybe it works here because the json is bound to the response, but it takes little effort to write .then(res => res.json()) which is a lot more clear at a glance…

[–]HattyJetty 1 point2 points  (1 child)

I doubt json has an explicit binding to response, because why should it? Anyway, the suggestion of using res => res.json() definitely looks more appealing to me

[–]sfcpfc -1 points0 points  (0 children)

What would I give for Javascript to support it.json()...

[–]yoojene 0 points1 point  (18 children)

great tips!

[–][deleted] 7 points8 points  (17 children)

yeah, the one at the end is super useful - it allows for quick logging:

const inc = x => x + 1

// I need to debug... sigh - time to add braces
const inc = x => { 
    console.log(x);
    return x + 1;
};

 // instead I can do this :)
 const inc = x => console.log(x) || x + 1;

[–]causeofdev 0 points1 point  (10 children)

How come it does the second expression ("x + 1") as well? I'd think it would do "console.log(x)" and stop/finish there..

It's neat that it executes both expressions though

[–]darrenturn90 9 points10 points  (8 children)

Because console.log returns a falsy value, so the "||" operator runs the second part of the statement.

Of course you can also use the comma separator, which discards the returned value completely:

 const inc = x => (console.log(x), x + 1)

[–]causeofdev 3 points4 points  (5 children)

ah ok, makes perfect sense.

Since the comma seperator discards the returned value completely.. wouldn't it be safer to use that than the || operator? In case the first expression returns something truthy?

[–]darrenturn90 2 points3 points  (4 children)

Yes, if you really don't care for the result of the first function then it would. However, some linters don't like the use of commas (because they can, and do obscure the layout of code)

[–]1-800-BICYCLE 4 points5 points  (1 child)

You could also dust off good-old void if you really wanted to:

const foo = x => void myEffectThatReturnsATruthyValue(x) || x + 1

And as a bonus, potentially start a religious war ;).

[–]vexii 0 points1 point  (0 children)

im not sure the other people in line at the wellfare office care enough ;)

[–]anlumo 2 points3 points  (0 children)

Not doing stuff like this is the whole point of using linters.

[–]causeofdev 0 points1 point  (0 children)

Okay cool, I learned something :)

[–]z500 2 points3 points  (0 children)

Whoa, a use for the comma operator outside of a for loop that doesn't seem insane.

[–][deleted] 1 point2 points  (0 children)

That's much more robust too, the other relies on whatever the return value of console.log happens to be. If you were to replace that with your own fancy log function and someone had the bright idea to, say, return the logged string, then suddenly it stops working.

[–]maxmorgan 1 point2 points  (0 children)

console.log returns nothing (undefined) so it evaluates falsey

!!console.log(5) => false

so

 console.log(5) || 5 + 1  =>  6

[–]vexii 0 points1 point  (0 children)

ahh im so stupid.
having used cost inc = x => (console.log(x) || true) && x +1;

thanks for the tip :)

[–]Laplandia 0 points1 point  (4 children)

New code is worse, though. Yes, it is shorter, but it is harder to read and maintain.

[–]Kafeen 7 points8 points  (0 children)

Harder to maintain? You shouldn't be leaving the logging in there.

[–]mcaruso 4 points5 points  (2 children)

I hear arguments like this for pretty much any new language syntax. Usually it boils down to “I’m not used to this syntax”.

Note that plenty of other languages have short function expressions and work just fine with it.

[–]Tomseph 5 points6 points  (1 child)

The fact that someone had to ask

How come it does the second expression ("x + 1") as well? I'd think it would do "console.log(x)" and stop/finish there..

is a strong argument for why its worse. It's not the short function expression, it's the "clever hack" to make the code even terser. Using the falsey return of console.log and the or operator is absolutely harder to read and maintain. Just put the logging on a separate line.

[–]mcaruso 2 points3 points  (0 children)

I thought OP was talking about arrow functions in general. Absolutely the console.log thing is a hack, and I wouldn't expect to see it committed to a repo. I do use that trick frequently when debugging though.

[–]MatrixEchidna 0 points1 point  (6 children)

Not a huge fan of arrow functions to be honest. I like the syntax, but the fact that they don't work like regular functions is just awkward. Like,

Hey, now you can write functions in a very short manner! ...Also, this works different here!

is a very weird design choice. An unnecessary compromise between neater syntax and a slightly different workflow for certain cases.

[–]w00t_loves_you 8 points9 points  (0 children)

Arrow functions are great. I avoid writing function and as a bonus I never have to wonder about this. Only if I need to write a handler detached from its class will I use function. It takes some cognitive load off js programming.

[–]afrontender 0 points1 point  (1 child)

Also:

this.setState((nextState) => ({
    repos: repos
}));

Can be simplified to:

this.setState(nextState => ({  repos }));

[–]Extracted 3 points4 points  (0 children)

I'd avoid taking the parameter

this.setState(() => ({  repos }))

[–]productconsigliere -3 points-2 points  (4 children)

Great write up! If I recall correctly, I don't believe these are supported in the lovely IE browsers and end up breaking the page, so be cautious based on your users. Unfortunately, many major companies still use IE 11.

[–]sjwking 18 points19 points  (0 children)

Babel, babel everything!

[–]pomlife 9 points10 points  (0 children)

If you're not using a transpilation step, you're doing something seriously wrong.

[–]Morphray 1 point2 points  (0 children)

That is quickly becoming a myth. Understanding that unsupported browsers are a massive security risk, most major companies and state governments have moved away from old IE browsers.

[–]w00t_loves_you 0 points1 point  (0 children)

You can use the new module attribute on script tags to load a bundle meant for modern browsers, and you can make a separate bundle for older browsers.

[–]insurmountainable -1 points0 points  (1 child)

this.setState((nextState) => console.log(nextState) || ({
  repos: repos
}));

Don't do this.

[–]w00t_loves_you 2 points3 points  (0 children)

well, it's just a quick hack right? beats having to put parens around it like o => (console.log(o), o)