Menu
Try in Playground

JavaScript Arrow Functions: =>, this, and When to Use Them

How arrow functions work in JavaScript — the => syntax, implicit returns, how they handle this, and when to reach for one instead of function.

A Shorter Way to Write a Function

Arrow functions are JavaScript's terser syntax for defining a function. They showed up in ES2015 and are now the default style for small, inline functions — especially callbacks passed to array methods, promise handlers, and event listeners.

The shape is: parameters, then =>, then the body.

index.js
Output
Click Run to see the output here.

Same result as the classic form:

const add = function (a, b) {
    return a + b;
};

Less typing is nice, but the real reasons to care about arrow functions are the implicit return and how they treat this. Both are coming up.

Implicit Return

If the body is a single expression, you can drop the braces and the return. The expression's value is returned automatically:

index.js
Output
Click Run to see the output here.

This is where arrow functions shine — one-line transforms read like math:

index.js
Output
Click Run to see the output here.

The moment you need more than one statement, you're back to braces and an explicit return:

index.js
Output
Click Run to see the output here.

Forgetting the return inside braces is the most common arrow-function mistake. x => { x * 2 } returns undefined — the braces turn the body into a block, and the expression inside is thrown away.

Parameter Parentheses

With exactly one parameter, the parentheses are optional:

index.js
Output
Click Run to see the output here.

With zero, two, or more parameters, you need them:

index.js
Output
Click Run to see the output here.

Some teams prefer always-parentheses for consistency. Both styles are fine — pick one and stick with it.

Returning an Object Literal

Here's a gotcha. If you try to implicitly return an object, the braces look like a function body:

index.js
Output
Click Run to see the output here.

That prints undefined. JavaScript reads { name: name } as a block with a labeled statement, not an object literal. Wrap the object in parentheses to force it to be an expression:

index.js
Output
Click Run to see the output here.

The () around { ... } is the fix. File it away — you'll hit this within the first week of writing arrow functions.

Lexical this

The real reason arrow functions exist isn't the shorter syntax. It's that they don't have their own this. They inherit it from the surrounding scope.

To see why that matters, consider a regular function used as a callback:

index.js
Output
Click Run to see the output here.

Inside the function () { ... } passed to setInterval, this is not counter. Regular functions get their own this based on how they're called, and setInterval calls the callback with this as undefined (in strict mode) or the global object.

An arrow function keeps the this of the enclosing method:

index.js
Output
Click Run to see the output here.

Inside the arrow function, this is still counter because the arrow doesn't introduce its own this. Before arrow functions, people worked around this with const self = this; or .bind(this). Those patterns still work but are rarely needed now.

What Arrow Functions Don't Have

The lexical-this rule is part of a larger pattern: arrow functions skip several things that regular functions have.

  • No own this — inherited from the enclosing scope.
  • No arguments object — use rest parameters (...args) instead.
  • No new — you can't use an arrow function as a constructor.
  • No prototype property — follows from the no-new rule.
index.js
Output
Click Run to see the output here.

...args gives you the same "accept any number of arguments" capability that arguments did, with the bonus that it's a real array. The new Greeter(...) call throws because arrow functions aren't constructors.

When Not to Use an Arrow Function

Arrow functions are the default for callbacks, but they're the wrong choice in a few spots:

index.js
Output
Click Run to see the output here.

Object methods defined with arrow syntax don't get this bound to the object — they inherit it from wherever the object literal was written (usually the module or global scope). Use the shorthand method syntax (greet() { ... }) for methods.

Same idea for class prototype methods, event-handler methods that need this to refer to the element, and any function you plan to call with new. A regular function is the correct tool there.

A Quick Rule of Thumb

  • Short callback, one expression? Arrow function.
  • Need this to stay bound to the outer scope? Arrow function.
  • Defining a method on an object or class prototype? Regular function (or shorthand method).
  • Writing a constructor? Regular function, or better yet, a class.

You'll see both styles in any real JavaScript codebase. Knowing which one fits takes a few weeks of reading other people's code — after that, the choice becomes automatic.

Next: Parameters and Defaults

Arrow functions and regular functions share the same parameter features — default values, rest parameters, destructured arguments, and more. That's the next page, and it applies to every function form you've seen so far.

Frequently Asked Questions

What is an arrow function in JavaScript?

An arrow function is a shorter way to write a function, using the => syntax. const add = (a, b) => a + b; is an arrow function that takes two arguments and returns their sum. Besides the terser syntax, arrow functions don't bind their own this, arguments, or super — they inherit them from the surrounding scope.

What's the difference between arrow functions and regular functions?

Regular functions declared with function have their own this, their own arguments object, and can be used as constructors with new. Arrow functions have none of those — they inherit this from wherever they're defined. Arrow functions also can't be hoisted the way function declarations are.

When should I use an arrow function?

Reach for arrow functions for short callbacks (arr.map(x => x * 2)), and anywhere you want this to stay bound to the enclosing scope — like inside a class method that passes a handler to setTimeout or an event listener. Use a regular function for methods on objects, constructors, and standalone top-level functions.

Learn to code with Coddy

GET STARTED