Functions are first-class objects: create them three ways, pass them around, return them — and pick arrows or regular functions for the right reasons.
Three ways to define a function
// 1. Declaration — hoisted completely
function add(a, b) {
return a + b;
}
// 2. Expression — a value assigned to a variable (optionally named)
const multiply = function mul(a, b) {
return a * b;
};
// 3. Arrow function (ES2015) — concise, lexical `this`
const square = (x) => x * x;
const makePoint = (x, y) => ({ x, y }); // wrap object literals in ( )
console.log(add(2, 3), multiply(2, 3), square(4), makePoint(1, 2));
console.log(multiply.name, square.name, add.length);5 6 16 { x: 1, y: 2 }
mul square 2Declarations are hoisted, expressions are not
console.log(early()); // works: whole declaration is hoisted
function early() { return "declared"; }
try {
late();
} catch (e) {
console.log(e.name + ": " + e.message);
}
const late = () => "expression";declared
ReferenceError: Cannot access 'late' before initializationArrow vs regular functions
Regular function | Arrow => | |
|---|---|---|
this | Set by how it is called | Inherited from the enclosing scope (lexical) |
arguments | Yes | No (use rest ...args) |
Can be used with new | Yes | No — TypeError |
prototype property | Yes | No |
| Hoisting | Declarations are hoisted | Like any const — TDZ |
| Best for | Methods, constructors, generators | Callbacks, short transforms, keeping outer this |
const Arrow = () => {};
try {
new Arrow();
} catch (e) {
console.log(e.message);
}
console.log(Arrow.prototype, typeof function () {}.prototype);Arrow is not a constructor
undefined objectFunctions are objects
function greet(name) { return `Hi ${name}`; }
greet.calls = 0; // attach properties like any object
const fns = [greet, (s) => s.toUpperCase()];
console.log(fns.map((f) => f("x")));
console.log(typeof greet, greet instanceof Object, greet);[ 'Hi x', 'X' ]
function true [Function: greet] { calls: 0 }Return values
A function without
return(or with a barereturn;) returnsundefined.Arrow with a concise body (
x => x * 2) returns the expression; with braces you needreturn.Automatic semicolon insertion:
returnfollowed by a newline returnsundefined— keep the value on the same line.
function broken() {
return
{ ok: true };
}
const withBraces = (x) => { x * 2 };
console.log(broken(), withBraces(2));undefined undefinedWhat is the difference between a function declaration and a function expression?
When should you NOT use an arrow function?