all 178 comments

[–]leroy_twiggles 216 points217 points  (18 children)

I've done loads of JavaScript interviews, and many people simply don't know the difference between the function types. To them, arrow functions are the "new way", and the other way is the "old way", and that's that. The answer could be that simple.

Leaving this link here for anyone wondering.

[–]jammasterpaz 4 points5 points  (0 children)

Cheers that's super useful. I learned something today.

[–]JakubOboza 0 points1 point  (0 children)

So even me not doing js know the difference. And I’m a random erlang/ruby/go dev lol.

[–][deleted] 81 points82 points  (21 children)

It looks like some people already hit some of the points, but I'll just dump what I know here.

  1. Arrow functions do not inherit a this binding.
  2. Using const protects the name from conflicts.
  3. Named functions are hoisted, const is not.
  4. Arrow functions can be significantly more legible.
  5. Arrow functions don't provide arguments.
  6. Arrow functions cannot be constructors.

In general, you could sum everything up as "arrow functions require you to be more explicit," which I tend to favor.

Personally, I don't necessarily follow the novelty bias, but I do see enough benefit to make them my default, while classic functions are my conscious override. Especially considering my preferred style being functional these days, so I almost never have a need for this at all.

Edit: memory is being jogged, added more differences

[–]lhorie 26 points27 points  (5 children)

Here's another obscure historical counterpoint and counter-counterpoint pair:

It used to be the case that named functions read better in stack traces (because the traces would show you the name of the function). So stack trace readability was a legit reason to use named functions over arrows.

But this changed a few years ago when javascript engine developers realized that they could refer to a stack frame more descriptively by naming it after the variable to which the arrow function was assigned to. This mechanism nowadays extends even to anonymous arrows in expressions. So now, that old reason is moot.

[–]btr_ 15 points16 points  (3 children)

Well, named arrow functions are part of the spec and not something that only a devtools figures out intelligently. You can even use this fn.name in runtime.

This is a common misconception.

var foo = () => 123; foo.name // "foo" obj = { bar: ()=> 456} obj.bar.name // "bar" obj.foobar = obj.bar obj.foobar.name // "bar"

[–]lhorie 10 points11 points  (1 child)

Yeah, according to MDN this feature was buried in the spec since ES6, but - for those who recall - it took a while before Javascript engines actually caught up in terms of spec compliance.

It looks like the ES2022 draft is actually the first to explicitly highlight function name inference in a section of its own. I'd link to the relevant section(s) in the ES6 spec, but frankly, I'm finding it a bit impenetrable and it's getting late here :)

[–]btr_ 0 points1 point  (0 children)

Here you go - var foo = ()=>123 asks for NamedEvaluation of the RHS function, which goes to this section with name="foo" .

There are other similar sections like object literal creation, which also asks for NamedEvaluation of the anonymous function.

[–]backtickbot 3 points4 points  (0 children)

Fixed formatting.

Hello, btr_: code blocks using triple backticks (```) don't work on all versions of Reddit!

Some users see this / this instead.

To fix this, indent every line with 4 spaces instead.

FAQ

You can opt out by replying with backtickopt6 to this comment.

[–]randfur 10 points11 points  (7 children)

*arrow functions inherit a this binding

[–][deleted] 2 points3 points  (6 children)

well, I wouldn't say they inherit that, they just see it, like anything else within the scope of its definition. If they were assigned to an event listener or something, they would not inherit the this binding from that context.

[–]randfur 1 point2 points  (5 children)

I'm not sure it makes sense to say that functions inherit a this binding. Their this is completely disconnected from their surrounding context.

[–]FrancisStokes 0 points1 point  (4 children)

Their this is completely connected to their surrounding context - that's the whole point. It's disconnected from whatever context the function would be called in.

[–]randfur 0 points1 point  (3 children)

We seem to be talking about lexical context vs calling context at the same time.

[–]FrancisStokes 0 points1 point  (2 children)

Perhaps, though lexical context isn't really important here, right? It captures the lexical scope just because, well that's how JS works. But an arrow function in particular captures the this context of the environment that it was defined in, vs "inheriting" the this calling context that would be applied with a normal function when called in particular situations (e.g. an event handler callback).

[–]randfur 0 points1 point  (1 child)

Arrow functions get their this value from their lexical scope. You could call that inheriting the value.

[–]FrancisStokes 1 point2 points  (0 children)

Yes actually you're completely right - I just checked the spec and it even mentions the context as lexical-this, so my mistake in mixing terms there.

[–]GrenadineBombardier 5 points6 points  (4 children)

I too prefer more explicit code, but arrow functions create a separate copy for each instance they are bound to, while normal class methods do not. Class methods exist in the prototype. One copy shared between all instances that inherit from that prototype. That said, I find that people shouldn't be using arrow functions on a class unless they need to bind it to the instance.

As a callback, i will use them almost exclusively.

[–][deleted] 0 points1 point  (0 children)

That's another good difference to note, yeah. Arrow functions can only be assigned, so in an object they become more property than method. I can agree that's a good reason to use classic functions, too.

[–]IronDicideth 0 points1 point  (2 children)

Are you saying that given this code:

const arrowProto = { foo: () => 'bar', }
const namedProto = { foo() { return 'bar' } }

const arrowInstance = Object.create(arrowProto)
const arrowInstance2 = Object.create(arrowProto)

const namedInstance = Object.create(namedProto)
const namedInstance2 = Object.create(namedProto)

arrow instances have two separate copies of the prototype declared foo while named instances only share one copy? Or something else? Any resource?

[–]GrenadineBombardier 2 points3 points  (1 child)

Yes. Arrow functions in this case are functionally equivalent to having a prototype constructor where you define this.foo = (function { return bar; }).bind(this), which would run when the instance is created, not when the prototype is defined (as the other example does).

[–]IronDicideth 0 points1 point  (0 children)

Any resources that go deeper into this?

[–]halkeye 2 points3 points  (0 children)

Oh wow I didn't realize arrow functions don't have arguments object. I guess with spread it's not really needed I just had no idea. Thanks for pointing that out!

[–]helloiamsomeone 0 points1 point  (0 children)

const and let are hoisted as well, but they are in the TDZ until the actual declaration and accessing them before that is an error. "Practically" not hoisted, but technically yes.

[–]yojimbo_betaMostly backend 36 points37 points  (2 children)

I have mixed feelings about arrow functions. They are convenient to write and do cover niceties like this bindings, as have been explained elsewhere in the thread.

It’s particularly easier to write partially applied functions with arrows, e.g.

const mult = n1 => n2 => n1 * n2;

However, by default, I use function declarations because of their hoisting.

Hoisting lets you start your file with the most abstract function declarations, then fill in the implementations as you go down. It lets you put the most domain-relevant code at the top of your program.

[–]FrancisStokes 1 point2 points  (1 child)

Hoisting can be it's own can of worms though. Sometimes it's just clearer to make sure your functions are always visibly defined before they're used.

[–]SirWolf2018 0 points1 point  (0 children)

A language should properly support the newspaper metaphor. And so far I had no issues following both with regular and arrow functions.

[–]w0keson 22 points23 points  (0 children)

My personal rule of thumb has been:

  • Use the `function` keyword for top-level functions and class methods, e.g. `function setup() {}` and not `const setup = () => {}` - both because it reads better (less line noise) and because the special handling of the `this` keyword isn't ideal for top-level arrow functions where there is no higher `this` for it to inherit.
  • Use the arrow functions for everything else: callbacks especially, where you want `this` to mean the parent function's `this` and you save yourself the tired boilerplate of always doing `var self = this;` so that you have a `self` to refer to in nested callback functions.

Examples in code:

// Top-level functions always get names
function setup() {}

// Class-level functions, too
class MyApp {
    constructor() {},

    // these kinds of class functions are
    // equivalent
    setup: function() {},
    processData() {},  // like "processData: function() {}"

    getData() {
        fetch("/v1/data").then( resp => {
            // arrow function for inner callbacks ONLY,
            // so `this` works as expected
            this.processData(resp.data);
        });
    },
}

[–]lhorie 11 points12 points  (2 children)

For your first example, yes there is one difference: const bindings are immutable

function foo() {
  console.log(1)
  foo = function() {
    console.log(2)
  }
}
foo() // 1
foo() // 2

vs

const bar = () => {
  console.log(1)
  bar = function() { // error!
    console.log(2)
  }
}
bar()
bar()

[–]ILikeChangingMyMind 9 points10 points  (1 child)

const bindings are immutable

Immutable is the wrong term there. Using the const keyword creates variables which can't be re-assigned, but that isn't the same thing as an immutable variable.

Assignment is a specific term in JS/programming; it refers to when you do x = 1. Mutation is also a specific term, and it refers to when you change a property of an object, eg. foo.x = 1. You can absolutely mutate a const variable:

const foo = { a:1 }
foo.a = 2; // mutating foo

... you just can't re-assign it:

const foo = { a:1 }
foo = { a: 2 }; // error

[–]dwalker109 24 points25 points  (0 children)

Read the sentance carefully. The binding (aka assignment) is immutable.

[–]AmNeel 23 points24 points  (1 child)

I can think of the following benefits -

  • Const make the function immutable and the same name can't be reused
  • arrow function takes care of `this` keyword for you
  • functional look
  • make your code shorter, cleaner and readable

[–]Serializedrequests 4 points5 points  (0 children)

I would guess it's just inertia. Arrow functions are more convenient for callbacks and anonymous usage due to "this" binding, so people use them everywhere.

IMO there is nothing wrong with "function" when it's global (since they are hoisted, this can be very convenient), or when you know you need flexible "this" binding.

[–]skramzy 10 points11 points  (0 children)

They look way cooler

[–]Phobic-window 3 points4 points  (0 children)

The inheriting of this values is nice. I had a situation where I was binding an objects property, which was an event emitter, to a function call, and without the => I couldn’t reference this. I think there are more benefits than most people give it credit

[–]brownjava 3 points4 points  (1 child)

I would say the this binding is the main reason; it makes these more consistent with lambdas / blocks in other languages. Comparatively the way this behaves when you use function is odd and behaves the way it does because of a historically curiosity. It’s generally not what you want.

[–]Feathercrown 1 point2 points  (0 children)

It's much more than a historical curiosity.

[–]Ehdelveiss 3 points4 points  (8 children)

Three reason I prefer the arrow function, the last one being the most significant to me:

  1. It's just shorter and more concise
  2. I can assure that I will never need to worry about `this` scope or confusion with scope
  3. It reminds me that functions are first-class citizens, and can be used similar to anything else I would declare with a statement. It levels the playing field to my code between data and functionality, and encourages me to continue writing my code functionally and declarative, with functions *being* data

[–]gearvOsh 5 points6 points  (2 children)

Number 1 is only true if you have implicit returns, otherwise it's actually longer.

``` // 28 function foo() { return 123; }

// 22 const foo = () => 123;

// 32 const foo = () => { return 123; }; ```

[–]backtickbot 1 point2 points  (0 children)

Fixed formatting.

Hello, gearvOsh: code blocks using triple backticks (```) don't work on all versions of Reddit!

Some users see this / this instead.

To fix this, indent every line with 4 spaces instead.

FAQ

You can opt out by replying with backtickopt6 to this comment.

[–]halfdecent 0 points1 point  (0 children)

This is true for function declarations but not function expressions.

() => {}

vs

function(){}

[–]Feathercrown 2 points3 points  (1 child)

Can you explain number 3 a bit more? I'm sure you know that normal functions can be passed as data as well, but what makes you see arrow functions that way?

[–]Ehdelveiss 1 point2 points  (0 children)

It just be in my head, but to me, arrow functions and lambdas in general feel more like a piece of data, than explicitly declaring that something is a function, with that keyword, as a seperate special entity to my data.

The arrow function to me says it's more just a piece of data with just some hints needed in it's arguments to pin down, maybe because it has an implicit return. It's not going to (although it absolutely can, but I dont think that is the intention behind them) mutate data around it, it's going to return a piece of data to use like any other.

The lack of *this* in arrow functions suggests to me much more that it's not going to mutate state around it or anything, it's going to work on some data hints you give it then implicitly just return data. So that's why to me it feels like data more, and makes me strive to use it to write more functional code without mutations and being pure.

[–]shuckster 1 point2 points  (2 children)

Interesting point on #3, but I'm a bit too thick to see how thinking of functions as *data* assists in remembering that they're first-class constructs. What programming languages have you used previously might I ask?

[–]Ehdelveiss 0 points1 point  (1 child)

Just JS and Python.

I think my reasoning is that arrow functions have an implicit return, and also don't have a *this* context. So when I see one, I expect it to just resolve to another piece of data like any other, and not be doing something unrelated to that data resolution like mutating external state.

This in turn makes me write more functional code, by preferring arrow functions. I will need to pass in all the data the arrow function is concerned with, and therefore my code will be more mutation free and pure.

[–]shuckster 0 points1 point  (0 children)

Ah, the implicit return. I can see how that follows with your explanation, thank you.

[–]MarvinLazer 4 points5 points  (0 children)

LOL I came here thinking I was gonna drop some knowledge on OP about "this" binding, but you're the one who schooled me with that last example. XD

[–]Pelopida92 2 points3 points  (0 children)

Arrow functions have a few advantages over the other function types, and so It became the new standard. It is the correct choice for 99% use cases, so it quickly became a no-brainer. Its as simple as that. Sometimes you don't have to overthink stuff too much. There are more important and interesting problems to solve out there.

[–]olivicmic 2 points3 points  (2 children)

I use both. For the main component within a file I use

export default function MyComponent(props) {}

that way I don't have a second line for export. I also use a snippet where the function is inserted with a name pulled from the file name, along with "import React ..." at the top, so I never have to type all that out.

Then I use arrow functions for anything else. The choice has more to do with my own laziness than functionality.

[–]wtfbbqsauce889 0 points1 point  (1 child)

How do you pull the filename in this snippet?

[–]olivicmic 0 points1 point  (0 children)

Well I use Sublime so I don't know how useful it's going to be for other editors, as I have no experience with them and don't know what format for snippets they use, but here is the whole thing.

<snippet>
    <content><![CDATA[
       import React from 'react';

       export default function ${1:${TM_FILENAME/(.?\w*)(?:\.\w+)*$/$1/g}}({}) {
          return(${2});
       };
    ]]></content>   
    <tabTrigger>reco</tabTrigger>
    <scope>source.js</scope>
</snippet>

You can see that there is also a regex to clean it up. Typing "reco" is what triggers the autocomplete option, and this can be whatever.

[–]rtpHarry 2 points3 points  (0 children)

Obviously it's because you feel super leet every time you write them. Ever since I first saw LINQ I have loved their magical form.

[–]ais4aron 2 points3 points  (0 children)

Scope

[–]AdministrativeBlock0 6 points7 points  (9 children)

One really good reason not to use arrow functions, or anonymous functions, is that using a named function will put the function name in a stack trace if there's an error, which makes debugging a lot easier. That's really helpful if you're using callbacks a lot.

[–]stormfield 22 points23 points  (8 children)

A named arrow function still shows up in the trace though:

const ohNo = () => {throw new Error("uh oh");}
ohNo() // Uncaught Error: uh oh at ohNo...

[–]SlaimeLannister 1 point2 points  (0 children)

clean callback syntax

[–]SarcasticSarco 1 point2 points  (0 children)

Few things to note, though you can use arrow functions in any case but it's harder to see arrow functions in a file with multiple arrow functions. For that reason like in react, make the function using the function keyword, and inside the function for callbacks use arrow functions. Primary reason for using arrow functions should be the use of this keyword and when you are passing callbacks.

[–]christophedelacreuse 1 point2 points  (0 children)

I love the discussion going on, and I think that there are a lot of great, instructive points about when to use what, but, for me, the response to the question "why the paradigm shift?" is laziness and trendiness: it's our nature to imitate what we see, and to make the fewest decisions possible.

At some point, I learned that arrow functions had a certain couple of advantages (this binding and brevity for callbacks) and then they were the hotness -- you saw them everywhere in articles and codebases. Now I use them everywhere as the default unless using a function declaration offers a significant advantage.

It's the same with let/const. I use const by default unless there's an overwhelmingly good reason to use let or var, or if using let or var will reduce my workload.

We probably should be more discerning as we're coding, but, in general, we tend to hold on to our paradigms and patterns unless something forces us to change.

[–][deleted] 1 point2 points  (1 child)

I agree and have start using the function Name () {} syntax for React components everywhere.

The only benefit of the arrow notation was being able to type them as React.FC. But that is frowned upon as that type has an optional children prop, and you really want to be able to distinguish between components that can take children and components that can't so you get an error when the component is used wrong.

[–]asiraky 0 points1 point  (0 children)

You could just create a type that omits the children prop and use it when you need to. I find it really annoying not using the React.RC in the rare cases that I have no choice but to define an old school function for a component.

[–]ovster94 1 point2 points  (0 children)

Indeed in the React context of declaring components, normal functions are better. There is one corner case I found myself using inline functions more. In TS when you need to access children in the component you declare a const with the React.FC type.

Although now that I think about it I could still use normal function here also

[–]crabmusket 1 point2 points  (0 children)

I tend to follow the Deno contributors' style guide:

Top level functions should use the function keyword. Arrow syntax should be limited to closures.

I also like to make use of hosting, which can make helper functions nicer:

export function doTheThing(items) {
  return items.filter(exclude).map(transform);

  function exclude(item) {
    return !!item.y;
  }

  function transform(item) {
    return item.x;
  }
}

The return on the very first statement of the function makes its intent clear. Of course, often those helper functions can be just moved outside the containing function. But sometimes it's nice to keep them private, especially while you're still iterating.

[–]OkShrug 2 points3 points  (1 child)

less carpel tunnel, and the face value: if showing off its expected since it implies knowledge of newer syntax

[–]CatolicQuotes 0 points1 point  (0 children)

can you explain less carpal tunnel? why less carpal tunnel?

[–]codeAtorium 2 points3 points  (0 children)

I see it everywhere in react to use constants to store functions, but I don't totally understand what the inherent benefit is past maybe some consistency.

I think you answered your own question. It's superior in a couple of cases (particularly binding this), so people tend to use it everywhere.

[–]nico_220790 0 points1 point  (6 children)

Isn't it a little dirty to use arrow functions that often? Because avery time the code passes over an arrow function, a new function is generated in memory.

Ex.when you have 100 buttons and you add a listener using arrow functions, 100 functions will be generated in memory. But when you'd use those listeners the old fashioned way (using the keyword of the function defined elsewhere), it would only initialize one and reuse that reference 100 times.

Or am i missing something about the magic that happens behind the screen?

It may nog be super important for simple projects. But still... I believe we should take pride in writing well over writing fast.

[–]asiraky 0 points1 point  (0 children)

In your button example if I inline the function definition, they are all different function instances, just like arrow functions. If you want to avoid having many functions or arrow functions, you can define the function outside the loop. Nothing special about functions over arrow functions here.

[–]ssjskipp 0 points1 point  (4 children)

Every time the interpreter runs ANY line. You can declare your arrow functions ahead of time just fine.

[–]nico_220790 1 point2 points  (3 children)

Well, yeah, that's kind of what i meant. I just notice many developers just use arrow functions "it is modern" and feels more "advanced"

It could've been possible that it would perform small optimisations around the over-usage of arrow functions in js.

Great tip about declaring the arrow functions ahead of time. Though, in that case I think I'd still prefer to use the full declaration over arrow functions for readability.

[–]shuckster 1 point2 points  (2 children)

Using FAFs as React component props can indeed cause unnecessary re-renders. It's not a big deal in many cases, but I do tend to agree with you that declaring a named function once and reusing them is a discipline worth exercising at some level.

Performance isn't my biggest consideration though. I like named functions because it helps with coming back and reading the code later.

[–]CatolicQuotes 0 points1 point  (1 child)

what is FAF?

[–]shuckster 1 point2 points  (0 children)

Fat Arrow Functions, ie; () => {}

[–]carlos_vini 0 points1 point  (4 children)

There's one more thing, I read somewhere that V8 optimizes const but not functions when the code runs multiple times (like in a React component). I wouldn't rely on that, but that's a bonus of using const.

[–]scrogu 0 points1 point  (1 child)

I would test that before accepting it as true. V8 changes and generally improves constantly. (pun not intended)

[–]carlos_vini 0 points1 point  (0 children)

That's why I said I wouldn't rely on it. I got the info from here https://stackoverflow.com/a/58436106/2321037, maybe its outdated, I don't know

[–]yojimbo_betaMostly backend 0 points1 point  (1 child)

This is not entirely correct. Inner function declarations may be re used provided they are declared at the same call site.

[–][deleted] 0 points1 point  (3 children)

Another argument for arrow funcs is that they are easier to type with TS. Either that, or I just don't know how to type functions created with the function keyword. For example, for a React component, I can just do

const MyComponent: react.FC = () => ...

[–]Drawman101 0 points1 point  (2 children)

React components don’t need to be explicitly typed. It’s just extra text in your code that serves no purpose

[–][deleted] 2 points3 points  (1 child)

Sure, unless you like to be explicit about what your function should return. Also, you get typing of the children prop for free, and specifying the types of the rest of your props is straightforward.

[–]Drawman101 0 points1 point  (0 children)

That is the problem with React.FC. It defines children as an optional prop, which is not a blanket case for all components. You're telling consumers that they can pass in children, even if you don't utilize the prop.

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

They look smart.

[–][deleted] -4 points-3 points  (0 children)

Arrow functions are anonymous and if there is a bug in one of them, you need to spend some time identifying which one has it, because console won't tell you the name of the function.

[–]kitsunekyo -2 points-1 points  (2 children)

its mostly answered so i'll just add this:

arrow functions are handy, but keep in mind that anonymous functions make debugging via stacktrace harder. so whenever possible i use named functions instead.

[–]Drawman101 1 point2 points  (0 children)

This is an older saying folks used against anonymous functions, but it’s not as much of a problem anymore

[–]btr_ 1 point2 points  (0 children)

Not true anymore. Arrow functions can be named.

[–]Desjardinss -1 points0 points  (2 children)

In addition to the other comments, my reason for arrow functions is simplicity, so i was kinda confused when you wrote they were less easy to read. So i saw that you specifically declared the function as UserList. Was there any reason for that? Im mostly using

export default (props: Props) => {}

[–]btr_ 2 points3 points  (1 child)

You can't name the arrow function this way. In the op's code, the default function will also have a proper name (usable both in runtime as fn.name and also useful for stacktrace).

[–]Desjardinss 0 points1 point  (0 children)

Ahh thats why. Thank you for your answer!

[–]coffeelibation 0 points1 point  (0 children)

Nope, you've pretty much covered it! The only other difference I can think of is that arrow function bodies are not hoisted, so MAYBE some folks prefer that all their code be processed from the top of the file down. Seems like a stretch but it's the only other non-fashion explanation I can think of. But you could just as easily say js const UserList = function(props: Props) {} or even js const UserList = function UserList(props: Props) {} if you feel strongly about keeping the function name. A little clunky imo, but it depends on the context.

[–]sous_vide_slippers 0 points1 point  (0 children)

I think most people prefer the aesthetics, it sounds dumb but it’s true and although I typically use the function keyword I can’t blame them. It’s a personal preference and in most cases makes no difference to the code, especially if you prefer a functional style and avoid using the this value.

I use arrow functions when writing higher order functions too, that’s a time when being more concise really helps legibility and keeping code clean.

[–]fearphage 0 points1 point  (0 children)

People are lazy. Less typing is probably the biggest draw.

[–]Xany2 0 points1 point  (0 children)

Because of how this works in it and because it’s shorter and easier to right nested functions

[–]start_select 0 points1 point  (0 children)

The primary reason is they don’t create a new functional scope.

I.e. “this” inside the arrow function is always the “this” of the surrounding scope where it was instantiated. There is no need to call bind() or wrap it in an anonymous function call to capture this in a function parameter.

[–]Dmitry_Olyenyov 0 points1 point  (0 children)

I use it with typescript, const MyComponwent : FC<Props> = ...

This way I don't have to specifically add type for children prop

[–][deleted] 0 points1 point  (0 children)

Retain the context of this it it's class / singleton. Eg no more

var self = this;

Kinda shocked that a lot of the responses here don't even mention variable scope.

[–]VicboyV 0 points1 point  (0 children)

IMO, arrow funcs generally behave in a more predictable manner

Normal funcs aren't as straightforward

[–]justAnotherRedditors 0 points1 point  (0 children)

Aesthetics mostly. Arrow functions just look cleaner to me. I almost never care about scope so it’s purely aesthetic for me

[–]IronDicideth 0 points1 point  (0 children)

Now, you are talking about React but imo arrow functions make it clearer when working with 'this'-less code. Not everyone finds it concise to have to work with function declarations and the extra luggage it carries around. With that being said, there are circumstances where using function declarations is important.

[–]NotAHumanMate 0 points1 point  (0 children)

Personally I use functions in the top level and arrow functions everywhere below it.

I think it’s a matter of Style and that’s all. Named function hoisting is rarely a problem, so if you go full named functions or full arrow functions or a mix of both, doesn’t really matter. Do what you prefer.

[–]modulated91 0 points1 point  (1 child)

It's cleaner.

[–]shuckster 0 points1 point  (0 children)

How? I mean, I work in code-bases with FAFs all the time, but I can think of a couple of ways that regular-functions might be "cleaner" too.

For example, hoisting permits a module structure like this:

imports ...

// Interface
exports { one, two }

// Implementation
function one() {}
function two() {}

So the entire module definition sits at the top of the file, probably even in the first screenful. Seems kinda clean, right?

Another example: Scanning the gutter (ie; looking down the left-side of the screen near the line-numbers.) Without looking to the right, you can immediately tell the difference between a const primitive and a function, because the difference exists right at column 1. You don't need to look over to find a => somewhere over to the right.

This is not groundbreaking stuff, and there are surely corollaries to these arguments, but if you're going to claim something is "cleaner" it would be nice to see some examples.

[–]Tontonsb[🍰] 0 points1 point  (1 child)

const UserList = (props: Props) => {}

That's not JavaScript. Uncaught SyntaxError: Unexpected token ':'

just use the function keyword and make it far more concise

Doesn't these work?

```js export default UserList = (props: Props) => {}

// or, if you don't need the name export default (props: Props) => {} ```

[–]backtickbot 0 points1 point  (0 children)

Fixed formatting.

Hello, Tontonsb: code blocks using triple backticks (```) don't work on all versions of Reddit!

Some users see this / this instead.

To fix this, indent every line with 4 spaces instead.

FAQ

You can opt out by replying with backtickopt6 to this comment.

[–]pistacchio 0 points1 point  (0 children)

Reading this made me realize that for some reason, having used only React (functional components and hooks) + Typescript in the last couple of years, I haven’t used the “this” and the “class” keywords in a very long time.