JS CodeLab

JavaScript Functions Guide: Declarations, Expressions & Arrow Functions

By JS CodeLab Engineering Team•Last updated: October 12, 2026•5 min read

Direct Answer & Key Concept

A JavaScript function is a reusable block of code designed to perform a specific task, accept arguments, and return computed results. JavaScript functions are first-class citizens, meaning they can be assigned to variables, passed as arguments, and returned from other functions.

Runnable Code SnippetRun in Playground
// Comparing Function Declarations and Arrow Functions
function calculateTax(subtotal, rate = 0.08) {
  return subtotal * rate;
}

const formatCurrency = amount => "$" + amount.toFixed(2);

const total = 100;
const tax = calculateTax(total);
console.log("Tax:", formatCurrency(tax)); // Tax: $8.00
console.log("Final Total:", formatCurrency(total + tax)); // Final Total: $108.00

What is a function in JavaScript?

A JavaScript function is a fundamental building block of web applications that groups statements together into an invocable, reusable procedure. In JavaScript, functions are first-class citizens (first-class objects). This means functions can be stored in variables, passed into callbacks, returned from higher-order functions, and augmented with dynamic properties just like standard objects.


What are the types of functions in JavaScript?

Modern JavaScript provides multiple ways to declare and invoke functions, each serving distinct architectural patterns:

| Function Type | Syntax Example | Hoisted? | Own this Context? | Has arguments object? | Constructor (new)? | | :--- | :--- | :--- | :--- | :--- | :--- | | Function Declaration | function add(a, b) { return a + b; } | Yes (full body) | Yes (dynamic) | Yes | Yes | | Function Expression | const add = function(a, b) { return a + b; }; | No (variable hoisted) | Yes (dynamic) | Yes | Yes | | Arrow Function (ES6) | const add = (a, b) => a + b; | No | No (lexical this) | No (use rest ...args) | No |


When should you use Arrow Functions vs Traditional Functions?

Introduced in ECMAScript 2015 (ES6), arrow functions provide both a compact, concise syntax and fundamentally altered binding semantics:

1. Lexical this Binding

Traditional functions establish their this context dynamically based on how they are called at runtime. Arrow functions, by contrast, do not bind their own this; they lexically inherit this from the surrounding execution context. This makes arrow functions ideal for callbacks, timer functions (setTimeout), and array pipeline iterations (map, filter).

const timer = {
  seconds: 0,
  start() {
    // Arrow function captures lexical 'this' from timer object
    setInterval(() => {
      this.seconds++;
    }, 1000);
  }
};

2. Implicit Return Syntax

When an arrow function contains only a single expression, the curly braces and return statement can be omitted:

const square = x => x * x;
const makeUser = (id, name) => ({ id, name }); // Note parens around object literal

When NOT to use arrow functions:

  • Object methods: If you need this to point to the host object, use standard shorthand method syntax (greet() { return this.name; }).
  • Constructors: Arrow functions cannot be called with the new keyword and do not possess a .prototype property.
  • Event handlers requiring this element: DOM event callbacks that inspect this as the clicked DOM element should use regular function declarations.

What are Default Parameters and Rest Parameters?

Modern JavaScript simplifies function signatures by eliminating defensive parameter boilerplate:

Default Parameters

Default parameters allow initializing formal parameters with default values if no value or undefined is passed:

function paginate(page = 1, pageSize = 20) {
  return { offset: (page - 1) * pageSize, limit: pageSize };
}

Rest Parameters (...rest)

Rest parameters condense an indefinite number of arguments into a real array, replacing the outdated array-like arguments object:

function calculateTotal(discount, ...prices) {
  const sum = prices.reduce((acc, price) => acc + price, 0);
  return sum * (1 - discount);
}

Common Mistakes with JavaScript Functions

  1. Returning object literals without parentheses in arrow functions: Writing () => { a: 1 } interprets the braces as a function body block rather than an object literal. Wrap in parentheses: () => ({ a: 1 }).
  2. Calling arrow functions with new: Calling new MyArrowFunc() throws a runtime TypeError: MyArrowFunc is not a constructor.
  3. Assuming function arguments can be sliced directly: The legacy arguments object is an array-like structure without array prototype methods. Use modern rest parameters ...args instead.

Frequently Asked Questions About JavaScript Functions: Declarations, Expressions & Arrow Functions

Do arrow functions have their own this context in JavaScript?

No. Arrow functions do not define their own this binding; instead, they capture the this value of the enclosing lexical execution context at the time they are created.

What is function hoisting in JavaScript?

Function declarations are completely hoisted to the top of their scope during compilation, allowing them to be safely invoked before their appearance in the source code. Function expressions are not hoisted.

How do you implicitly return an object from an arrow function?

To return an object literal implicitly, wrap the object in parentheses: const getUser = id => ({ id, active: true }); Otherwise, the JavaScript engine treats the curly braces as an empty block statement.

What is the difference between arguments and rest parameters?

The arguments object is an array-like object available only in non-arrow functions that lacks array methods like map or filter. Rest parameters (...args) produce true JavaScript Array instances compatible with all array methods.

Related Runnable JavaScript Examples

Ready to test what you learned?

The best way to solidify your JavaScript skills is by writing and running code. Open our free online compiler and test your scripts with real-time console feedback.

Open JavaScript Compiler