JS - 03.03 - Arrow Function
Arrow functions are a concise syntax for defining functions using the =>
syntax, rather than the traditional function
keyword. They offer several advantages, such as more concise syntax and different behavior for this
.
let func = (arg1, arg2, ..., argN) => expression;
This defines a function func
that takes parameters arg1, arg2, ..., argN
, and evaluates the given expression
.
Regular Function Expression:
let func = function(arg1, arg2, ..., argN) { return expression; };
Arrow Function:
let func = (arg1, arg2, ..., argN) => expression;
Examples of Arrow Functions
Basic Arrow Functions
- Simple return (no block):
let sum = (a, b) => a + b; // Single expression, returns result automatically let double = n => n * 2; // Single parameter, no need for parentheses around the parameter const square = x => x * x; // Short form for single expression function let sayHi = () => alert("Hello"); // No parameters
When there is only one parameter, ()
can be omitted.
If body is single expression, rather than a block in braces, that expression will be returned from the function even without return
statement.
let age = prompt("What is your age?", 18);
let welcome = (age < 18) ? () => alert('Hello') : () => alert('Greetings');
Welcome();
// 18 is default,
// if less than 18, hello
// otherwise greetings
Arrow Function with a Block (Multi-line)
If you need multiple statements in the function body, you must use curly braces {}
and explicitly include the return
statement.
const roundTo = (n, step) => {
let remainder = n % step;
return n - remainder;
};
let sum = (a, b) => {
let result = a + b;
return result;
};
alert(sum(1, 2)); // 3
Arrow Function with No Parameters
When there are no parameters, use empty parentheses ()
:
const horn = () => {
console.log("Toot");
};
Arrow Function as Arguments
Arrow functions can be used in the same way as regular functions, including as arguments to other functions.
function ask(question, yes, no) {
if (confirm(question)) yes();
else no();
}
ask(
"Do you agree?",
() => alert("You agreed."),
() => alert("You canceled the execution.")
);
ask(
"Do you agree?",
function() { alert("You agreed.");},
function() { alert("You canceled the execution."); }
);
Arrow Functions and this
Arrow functions behave differently from regular functions when it comes to the this
keyword. They do not have their own this
. Instead, they inherit this
from the lexical scope (i.e., the surrounding context).
Arrow Functions Inheriting this
let user = {
firstName: "John",
sayHi() {
let arrow = () => alert(this.firstName); // `this` refers to the `user` object
arrow();
}
};
user.sayHi(); // Output: "John"
In this example, the arrow()
function inherits this
from the sayHi()
method, which refers to the user
object.
Arrow Functions in forEach
and Similar Methods
Arrow functions are useful in methods like forEach
because they preserve the this
context from the surrounding code:
let group = {
title: "Our Group",
students: ["John", "Pete", "Alice"],
showList() {
this.students.forEach(
student => alert(this.title + ': ' + student) // `this` refers to `group`
);
}
};
group.showList(); // Output: "Our Group: John", "Our Group: Pete", "Our Group: Alice"
In this case, the arrow function inside forEach
inherits this
from the showList()
method, which refers to the group
object.
Regular Function in forEach
If we use a regular function inside forEach
, the value of this
changes to undefined
in strict mode, or the global object (window
in browsers) in non-strict mode:
let group = {
title: "Our Group",
students: ["John", "Pete", "Alice"],
showList() {
this.students.forEach(function(student) {
alert(this.title + ': ' + student); // Error: `this` is undefined or refers to the global object
});
}
};
group.showList(); // Error: Cannot read property 'title' of undefined
Error because when forEach
runs function with this=undefined
by default. This doesn’t affect arrow functions because they don’t have this
.
Here, the function passed to forEach
does not have its own this
and refers to the global context instead of the group
object, leading to an error.
- Regular functions create their own
this
context, which means inside theforEach
method,this
is no longer thegroup
object. - Arrow functions do not create their own
this
; instead, they inherit it from the surrounding scope, making them ideal for cases like theforEach
method where you want to preserve the context.
Arrow Functions Cannot Be Used as Constructors
Since arrow functions do not have their own this
, they cannot be used as constructors. You cannot call an arrow function with new
.
const Person = (name) => {
this.name = name;
};
let john = new Person("John"); // Error: Person is not a constructor
In this example, Person
is an arrow function, and calling it with new
will throw an error because arrow functions don’t have their own this
, which is required for object creation via new
.
Summary of Arrow Functions
- Syntax: Arrow functions use the
=>
syntax, making them more concise than regular function expressions. - No
this
binding: Arrow functions do not have their ownthis
. Instead, they inherit it from the surrounding scope, making them useful for methods likeforEach
. - Single-expression functions: If the body is a single expression, the
return
keyword is implicit, and you can omit the curly braces. - Cannot be used as constructors: Arrow functions cannot be invoked with
new
because they do not have their ownthis
.
Arrow Function Quick Reference
Feature | Arrow Function | Regular Function |
---|---|---|
Syntax | () => expression | function() { return expression; } |
this Binding | Inherited from the outer scope (lexical this ) | this is dynamic, based on the call site |
Constructor | Cannot be used as a constructor (new is not allowed) | Can be used as a constructor |
Implicit return | Yes, for single expressions | No, needs an explicit return statement |
Parameter Parentheses | Omit parentheses for a single parameter | Always require parentheses |