Loading...
Loading...
In JavaScript there are several ways to declare functions: Function Declaration, Function Expression and Arrow Function. Each has its own features regarding hoisting, this usage, ability to be a constructor, and nuances in syntax and application.
| Characteristic | Function Declaration | Function Expression | Arrow Function |
|---|---|---|---|
| Syntax | function name() { ... } | const name = function() { ... } | const name = () => { ... } |
| Hoisting | Full (function accessible before declaration) | Partial (variable hoisted but function initialized only at declaration point) | No (when declared with const/let function doesn't hoist) |
Own this | Yes (depends on call) | Yes (depends on call) | No (lexical this, inherited from outer scope) |
arguments | Available | Available | No (use ...rest) |
Use with new | Yes (can act as constructor) | Yes (if declared as regular function) | No (Arrow Function can't be constructor) |
| Application | General functions, constructors | Closures, callbacks | One-liners, callbacks |
Function Declaration fully hoists. This means we can call such function even before its actual declaration in file.
hello(); // "Hello from Declaration!"
function hello() {
console.log("Hello from Declaration!");
}
Function Expression with var hoists as variable (becomes undefined before initialization), but function itself becomes available only after assignment line. If using const or let, no hoisting for function as ready value — you can't call function before its declaration.
// Example with var
console.log(typeof sayHi); // "undefined"
// sayHi(); // Error: sayHi is not a function
var sayHi = function () {
console.log("Hello from Expression!");
};
Arrow Function usually declared with const or let, so doesn't hoist as ready function. If trying to call arrow function before declaration, will get error.
// greet(); // Error: greet is not defined
const greet = () => console.log("Hello from Arrow!");
Function Declaration and Function Expression (if not arrow) have this context determined by call method (or .call, .apply, .bind binding).
Arrow Function doesn't have own this: it's lexically borrowed from scope where arrow function is declared.
const user = {
name: "Alice",
sayHello: function() {
console.log("Hello, I'm " + this.name);
},
arrowHello: () => {
console.log("Hello, I'm " + this.name);
}
};
user.sayHello(); // "Hello, I'm Alice" - this = user
user.arrowHello(); // "Hello, I'm undefined" - this taken from outer scope (global / undefined)
Function Declaration and Function Expression have pseudo-array arguments containing all function arguments.
Arrow Function doesn't have arguments, but you can use ...rest operator to get all arguments.
function sumAll() {
let total = 0;
for (const arg of arguments) {
total += arg;
}
return total;
}
const sumAllArrow = (...args) => {
return args.reduce((acc, curr) => acc + curr, 0);
};
new as it doesn't have internal [[Construct]] mechanism.