DEV Community

Cover image for Don t use arrow functions... (if you don t need to)
Eckehard
Eckehard

Posted on

Don t use arrow functions... (if you don t need to)

We can love them or hate them, but arrow functions often allow to write more compact code. Sometimes there are good reasons to use them, if you need to deal with "this" in your code. But often, they tend to be harder to read.

So, when or when not should you use arrow functions?

We can write Javascript functions multiple ways:

hello = function() { // conventional function
  return "Hello World!"
}
const hello = () => { // "arrow"-function
  return "Hello World!"
}
// arrow-function with implicit return
const hello = () => "Hello World!" 
Enter fullscreen mode Exit fullscreen mode

Especially the last version has some nice options to shorten expressions, if you combine arrow functions with the ternary operator:

// conventional function
function getcolor(flag) 
{
    if (flag)
        return = "green"
    else
        return = "red"
}

// Arrow-function
const getcolor = (flag) => flag ? "green" : "red"
Enter fullscreen mode Exit fullscreen mode

even the brackets () around (flag) are not necessary, but it is a good convention to place them to mark the (argument) of the arrow function. Here we possibly get the best from using Arrow functions. Code is shorter and pretty clear. But: be carful not to exaggerate this!

const decode = c => 
   (Array.isArray(c)) ? c.map(el => (el>0 ? el : -el)) : (c > 0 ? c : -c)
Enter fullscreen mode Exit fullscreen mode

This is working code, but what does it do? Hard to say... I often spent hours just to figure out, what a single line of code does. This is pure waste of time!

Keep it clear and simple

I want to encourage you to write readable code! Computer just do what the code tells them to do, but programmers are responsible to maintain the code. Writing readable code will save you time and make your live easier.

Are arrow functions really more compact?

For short functions, that simply return a value, the arrow syntax provides an option, to write more compact code. But the next example shows, that arrows => are not always shorter:

  function f(a,b) { ... }
  const f = (a,b) => { ... }  
Enter fullscreen mode Exit fullscreen mode

The function operator shows immediately: Here we define a function. This is not alwas and immediately clear with the arrow operator, specially if you use deeply nested functions inside.

Even if it saves some bytes, for the sake of readability, you should prefer the good old "function()" where possible!


Remember: One day of debugging can save you 5 seconds of writing more readable code...

Top comments (7)

Collapse
 
tao_xin_23db52b1401921dcb profile image
Tao Xin (vanjs.org)
function f(a, b) { ... }
Enter fullscreen mode Exit fullscreen mode

is semantically closer to:

let f = function(a, b) { ... }
Enter fullscreen mode Exit fullscreen mode

rather than

const f = function(a, b) { ... }
Enter fullscreen mode Exit fullscreen mode

This means

const f = (a, b) => { ... }
Enter fullscreen mode Exit fullscreen mode

is indeed less error-prone in terms of preventing accidentally function redefintion.

Also arrow functions are semantically simpler than function literal due to the lack of this binding and arguments object. The syntax is also quite comfortable for people with functional programming background.

Collapse
 
efpage profile image
Eckehard

Maybe we schould then call them not "functional" programmers, but arrow-programmers? Or "const" programmers?

This is just a bad habit everybody is so used to:

  • "prototype" defines a classs
  • "let" defines a variable
  • "const" defines whatever you like, and if it's an array or object, it is not even constant...

Keywords have a meaning for humans, the computer just consumes numbers. If keywords do something different than what they suggest, this is a shell game, not programming. Why not use a language where the meaning of keywords depends on the weekday? This would be even more fun....

Collapse
 
tao_xin_23db52b1401921dcb profile image
Tao Xin (vanjs.org) • Edited

let defines block-scoped variables while var defines function-scope variables.

IMHO, we should use the right keywords based on what they actually mean, rather than what they look like.

const means something that can't be reassigned in JavaScript, it means "compile-time values" in Rust, and means a complex thing in C++.

long means a signed 64-bit integer in Java but means a weird stuff in C++.

struct (roughly) means a class with default public visibility in C++, but means a value-typed record in C#.

Array in JavaScript means ArrayList in Java, List in C# and vector in C++, whereas vector means N-dimensional numeric tuple in other places.

Moreover, some keywords actually look very weird to non-programmers: Why does string mean a text? Why do float and double mean numbers?

If we ask programmers to choose keywords based on what they think these keywords should mean to humans, they will bring their own understandings. With different understandings, it leads to endless and meaningless arguments, something programmers are particularly passionate about.

I think the only alignment we can viably get is to align on the exact semantic in the context of the specific programming language we're using, even if the semantic might seem counterintuitive to some.

Thread Thread
 
efpage profile image
Eckehard • Edited

So, why don´t we use assembler then? It´s well defined, but nearly impossible to understand for humans. Have you ever tried to find a bug in an assembler code?

I´ve used a lot of different progamming languages over the time, and I found that the language has an effect on my work efficiency. You can write code in any language, even FORTH or LUA or even CSS, and possibly some exotic scripting language will give you quicker results ins some cases. But over time, and if your codebase grows, readability starts to matter more and more. Languages with a well defined syntax and strict rules make it easier for people and compilers to find errors.

Ambiguity is never really helpful. Surely, keywords may be different, but they should be unambiguously defined. What, if you define a double, but under certain circumstances, this can be a class definition? Or a string? That is, what we see in Javascript on on many places.

I know all the rules, but some things are simply confusing in Javascript. But only because it is possible, we do not necessarily need to use it.

I think it is worth to talk about how we can write more readable code. If you are happy with a different style, this is completely up to you.

Thread Thread
 
tao_xin_23db52b1401921dcb profile image
Tao Xin (vanjs.org) • Edited

What I meant is let means block-scoped variables in JavaScript and should be used in the places we want block-scoped variables, even if the keyword let looks a little bit different than "variable".

Similarly, arrow functions mean functions without this binding, thus can (and should, IMHO) be used as functions that don't need this binding.

Thread Thread
 
efpage profile image
Eckehard • Edited

We can assume than most people know the rules, but my question was: Is it good to use anything JS provides?

"This" is a good example. Let see, what MDN has to say:

A function's this keyword behaves a little differently in JavaScript compared to other languages. It also has some differences between strict mode and non-strict mode.

In most cases, the value of this is determined by how a function is called (runtime binding). It can't be set by assignment during execution, and it may be different each time the function is called. The bind() method can set the value of a function's this regardless of how it's called, and arrow functions don't provide their own this binding (it retains the this value of the enclosing lexical context).

That is a case where I woud say:

Don´t use "This" (as long as you do not need to)

This

"This" makes your code ambigous, it will behave differently in different context and it may be hard to determine, what is really does. If you need to access the "lexcial context", there are better ways to do it. I don´t say, it is not handy, sometimes, but you better avoid to use it as it makes you code harder to understand.

"This" or "Self" is used in C++ or Pascal to give methods access to the object they work in, and there is no other way to provide do this. So, there was very good reasons to introduce "This" or "Self", it is clearly defined and you can use "Self" in a reliable way.

Collapse
 
artydev profile image
artydev

Good reminder :-)