Suggest an editImprove this articleRefine the answer for “Ways to declare functions”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**JavaScript lets you declare a function in many ways: a function declaration, a function expression (anonymous or named), an arrow function, the `new Function` constructor, a generator `function*`, an `async` function, an object method shorthand, a class method, an IIFE and a bound function from `bind()`.** They differ in hoisting, in how `this` behaves, in whether `arguments` and `prototype` exist, in whether they can be called with `new` and in `super` support. ```javascript function sum(a, b) { return a + b; } // declaration, hoisted const mul = function (a, b) { return a * b; }; // expression const inc = x => x + 1; // arrow, lexical this ``` **Key point:** choose the form by the `this` semantics you need and by whether the function must be a constructor, not by which syntax is shorter.Shown above the full answer for quick recall.Answer (EN)Image**In JavaScript a function is a value, so the language offers several syntactic forms for creating one, from the classic `function` to arrows, generators and class methods.** The forms differ in more than looks: the choice decides hoisting, how `this` behaves, whether `prototype` exists and whether the function can be called with `new`. ## Theory ### TL;DR - A function declaration is hoisted, has its own `this` and can be a constructor. - A function expression is available only after the assignment, and can be anonymous or named. - An arrow function takes `this` lexically, has no `arguments`, no `prototype` and does not work with `new`. - Special kinds: `new Function` (built from a string, not recommended), `function*` (generator), `async function` (returns a `Promise`). - Object and class methods are functions too, but with `super` support through `[[HomeObject]]`. - IIFE and `bind()` are not new syntactic forms, they are ways to run a function immediately or to fix its `this`. ### Quick example ```javascript function sum(a, b) { // 1. function declaration return a + b; } const mul = function (a, b) { // 2. function expression return a * b; }; const inc = x => x + 1; // 3. arrow function const obj = { sayHi() { console.log('hi'); } // 4. method shorthand }; ``` ### Classic forms: declaration, expression, arrow **1) Function declaration** ```javascript function sum(a, b) { return a + b; } ``` - It is hoisted: the function can be called before its declaration in the code. - It has its own `this` when called as a function or as a method. - It can be used as a constructor (`new Sum()`). **2) Function expression** ```javascript const mul = function (a, b) { return a * b; }; ``` - No hoisting: the function is available only after the assignment. - It can be anonymous or named: ```javascript const fact = function factorial(n) { /* ... */ }; // named: the name is visible inside ``` The name of a named expression is visible only inside the function itself, which is handy for recursion and for a readable stack trace. **3) Arrow function** ```javascript const inc = x => x + 1; const sum = (a, b) => a + b; ``` - Lexical `this`: it is taken from the outer lexical environment. - No `arguments` (use rest parameters `...args` instead). - Cannot be used with `new`, has no `prototype`. - A great fit for callbacks and short functions. ### Special kinds: Function, generators, async **4) Function constructor** ```javascript const fn = new Function('a', 'b', 'return a + b'); ``` - Creates a function from a string, just like `eval`. - Not recommended: security and performance problems, plus the body is compiled in the global scope. **5) Generator function (`function*`)** ```javascript function* idGenerator() { let i = 0; while (true) { yield i++; } } ``` - Returns an iterator and supports `yield`. - Execution can be paused and resumed. **6) Async function** ```javascript async function fetchData() { const r = await fetch('/api'); return r.json(); } const fn = async () => { /* an async arrow works too */ }; ``` - Always returns a `Promise`. - You can use `await` inside it. Combinations are allowed too: `async function*` is an async generator for `for await...of`. ### Object and class methods **7) Method shorthand in objects** ```javascript const obj = { sayHi() { console.log('hi'); }, // method async load() { await fetch('/'); } // async method }; ``` - Convenient for methods: they have `[[HomeObject]]`, which means `super` works. - You can also write `prop: function () {}`, but that is a plain function expression with no `super` support. **8) Class methods (inside `class`)** ```javascript class C { method() {} static staticMethod() {} async asyncMethod() {} } ``` - A class declaration is not hoisted the way a function declaration is: before the `class` line runs, the class cannot be used. - Methods are used with instances or with the class itself and they support `super`. - A class body always runs in strict mode. ### Derived forms: IIFE and bind **9) IIFE, Immediately Invoked Function Expression** ```javascript (function () { // runs immediately })(); ``` - Useful for creating a local scope; before modules existed this was the main way to keep the global scope clean. **10) `Function.prototype.bind` (creating a bound function)** ```javascript function f() { console.log(this); } const bound = f.bind({ x: 1 }); ``` - Returns a new function with a fixed `this` and, optionally, with partially applied arguments. - Binding an already bound function again does not change the context. ### Common mistakes - Relying on hoisting for a function expression: calling `mul(2, 3)` above `const mul = function ...` throws a `ReferenceError`. - Declaring an object method as an arrow and expecting `this` to point at that object. - Using `new Function` or a string instead of a normal function: it carries the same risk as `eval`. - Forgetting that an `async` function returns a `Promise` and reading its result without `await` or `.then()`. - Confusing `prop: function () {}` with the shorthand `prop() {}`: the first has no `[[HomeObject]]`, so `super` does not work in it. - Declaring a function declaration inside an `if` block and expecting consistent behaviour across environments: use an expression instead. ### Comparing the forms | Form | Hoisting | Own `this` | `new` | `prototype` | | --- | --- | --- | --- | --- | | Function declaration | Yes | Yes | Yes | Yes | | Function expression | No | Yes | Yes | Yes | | Arrow function | No | No (lexical) | No | No | | `new Function` | No | Yes | Yes | Yes | | Generator `function*` | Yes (for a declaration) | Yes | No | Yes | | Async function | Yes (for a declaration) | Yes | No | No | | Object or class method | No | Yes | No | No |For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.