Functions are an essential building block in JavaScript and are used to perform a specific task or calculate a value. Functions are reusable pieces of code that can be called from anywhere in your program, as long as they are defined in the correct scope. To declare a function, you use the function keyword, followed by the function name and the block of code to be executed. Let's take a look at a simple function that logs a message to the console:
function sayHi() {
console.log("Hi");
}
To call or invoke the function, we simply use its name, followed by parentheses:
sayHi();
This will execute the code within the function, which in this case, logs "Hi" to the console. We can also declare functions with parameters, which are placeholders for values that will be passed in when the function is called. For example, we can modify our previous function to take in a name parameter:
function sayHiTo(name) {
console.log("Hi " + name);
}
To call this function, we would pass in a name value:
sayHiTo("John");
This would log "Hi John" to the console. Functions can also have access to variables within their scope, which means they can use and modify them. However, it's important to understand scoping in functions, as variables declared within a function are only accessible within that function's scope.
ES6 introduces some new features for functions, such as arrow functions and the spread operator. Arrow functions are a shorthand way of declaring functions and have a concise syntax. For example:
const sayHi = () => {
console.log("Hi");
}
The spread operator allows us to pass in an array as individual arguments to a function. For example:
function addNumbers(a, b, c) {
return a + b + c;
}
const numbers = [1, 2, 3];
addNumbers(...numbers);
This would return 6, which is the sum of the numbers array.
Default values in ES6 functions are a way of defining a default value for a function parameter in case no value is passed in. This saves us from having to check if a value is undefined and assign a default value to it. Here's an example:
function multiplyNumbers(x = 2, y = 5) {
return x * y;
}
multiplyNumbers(); // output: 10
multiplyNumbers(3); // output: 15
multiplyNumbers(3, 4); // output: 12
x
and y
, their default values are used. If we pass in only x
, the default value for y
is used. If we pass in both x
and y
, those values are used....
syntax is used to define a rest parameter. Here's an example:function logAllArguments(...args) {
console.log(args);
}
logAllArguments(1, 2, 3); // output: [1, 2, 3]
logAllArguments(4, 5, 6, 7); // output: [4, 5, 6, 7]
args
parameter is defined with the rest syntax. This means that any number of arguments can be passed to the function and they will be collected into an array.Rest parameters can be used to perform various operations on an array of numbers. Here are a few examples:
function sortNumbers(...nums) {
return nums.sort((a, b) => a - b);
}
console.log(sortNumbers(5, 3, 8, 1, 2)); // output: [1, 2, 3, 5, 8]
sortNumbers
function takes in an arbitrary number of numbers using the rest syntax. These numbers are sorted in ascending order using the sort()
method.function multiplyNumbers(multiplier, ...nums) {
return nums.map(num => num * multiplier);
}
console.log(multiplyNumbers(3, 1, 2, 3, 4)); // output: [3, 6, 9, 12]
multiplyNumbers
function takes in a multiplier
value and an arbitrary number of numbers using the rest syntax. The map()
method is used to multiply each number in the array by the multiplier
value.Rest parameters can also be used with the spread syntax to combine multiple arrays or objects into one. Here are a few examples:
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combinedArray = [...arr1, ...arr2];
console.log(combinedArray); // Output: [1, 2, 3, 4, 5, 6]
arr1
and arr2
and then use the spread syntax with the rest parameter ...
to combine them into a single array combinedArray
.Example 2: Combining objects
const obj1 = { name: "John", age: 30 };
const obj2 = { gender: "Male", city: "New York" };
const combinedObject = { ...obj1, ...obj2 };
console.log(combinedObject); // Output: { name: 'John', age: 30, gender: 'Male', city: 'New York' }
obj1
and obj2
and use the spread syntax with the rest parameter ...
to combine them into a single object combinedObject
.Example 3: Using rest parameters with other parameters
Rest parameters can also be used in conjunction with other parameters in a function. Here's an example:
function sum(...numbers) {
return numbers.reduce((acc, curr) => acc + curr);
}
console.log(sum(1, 2, 3)); // Output: 6
console.log(sum(1, 2, 3, 4, 5)); // Output: 15
sum
that takes in any number of arguments using the rest parameter ...numbers
. We then use the reduce
method to add up all the numbers and return the sum.Before we dive into arrow functions, let's review function expressions. A function expression is a way to define a function as a variable. Here's an example:
const sayHi = function() {
console.log('Hi!');
}
sayHi();
sayHi
using the function
keyword, and then assigned it to a variable called sayHi
. We can then invoke the function by calling sayHi()
.ES6 introduced a new way to write function expressions: arrow functions. Arrow functions are a more concise way to write function expressions. Here's an example of the same function we defined earlier, but using an arrow function:
const sayHi = () => {
console.log('Hi!');
}
sayHi();
function
keyword. Instead, we use an arrow (=>
) to indicate that we're defining a function.Arrow functions can take different forms depending on the number of arguments and the complexity of the function body. Here are some examples:
const multiply = (num1, num2) => {
return num1 * num2;
}
If the function body is a single expression, you can write it more concisely like this:
const double = num => num * 2;
This is equivalent to:
const double = num => {
return num * 2;
}
Here are some benefits of using arrow functions:
Concise syntax: Arrow functions are shorter and easier to read than function expressions.
return
keyword and the curly braces.this
: Arrow functions bind the this
value to the enclosing scope, which can make it easier to write code that works as expected.map
, filter
, and reduce
. Here's an example of using an arrow function with map
:const users = [
{ name: 'Chris', age: 60 },
{ name: 'Jane', age: 30 },
{ name: 'Billy', age: 45 },
];
const getUsernameList = users.map(user => user.name);
console.log(getUsernameList);
map
method to create a new array that contains only the names of the users. We're passing an arrow function to map
that takes a single argument user
and returns user.name
. The arrow function is more concise and easier to read than a traditional function expression.JavaScript allows you to set default values for function parameters. If the function is called without passing a value for the parameter, the default value will be used instead.
function greet(name = 'World') {
console.log(`Hello, ${name}!`);
}
greet(); // Output: Hello, World!
greet('John'); // Output: Hello, John!
greet
function has a parameter called name
with a default value of 'World'
. If the function is called without passing a value for the name
parameter, the default value of 'World'
will be used. If a value is passed, that value will be used instead....
) before the parameter name. function sum(...numbers) {
let total = 0;
for (let number of numbers) {
total += number;
}
console.log(`Total: ${total}`);
}
sum(1, 2, 3); // Output: Total: 6
sum(4, 5, 6, 7, 8); // Output: Total: 30
sum
function takes any number of arguments and calculates their total. The rest parameter numbers
is used to collect all of the arguments into an array. Then, a for...of
loop is used to add up all of the numbers and calculate the total.arguments
Objectarguments
object. For example, a function can be declared with only two expected arguments but can receive three, as shown below:function exampleFunction(x, y) {
console.log(arguments[2]); // Outputs the third argument passed in
}
exampleFunction(1, 2, 3); // Prints 3
arguments
object can be used to access all arguments passed to the function, even if they are not explicitly defined as parameters.However, it can be clunky to manipulate the arguments
object as it behaves like an object, not an array. It cannot be sorted or manipulated using array methods. Therefore, the arguments
object can be converted to an array using the slice()
method, as shown below:function exampleFunction(x, y) {
const args = Array.prototype.slice.call(arguments);
console.log(args); // Outputs an array [1, 2, 3]
}
exampleFunction(1, 2, 3);
arguments
object to an array, allowing us to manipulate it using array methods.ES6 introduced a simpler way to pass an indeterminate number of arguments using rest parameters. It is defined using three dots before a parameter name in the function declaration, as shown below:
function exampleFunction(x, y, ...rest) {
console.log(rest); // Outputs an array [3, 4, 5]
}
exampleFunction(1, 2, 3, 4, 5);
rest
parameter collects any additional arguments passed to the function, allowing us to access them as an array directly.this
Keyword in Fat Arrow Functions and Traditional Functionsthis
keyword is a special keyword that refers to the context in which the function is called. In a fat arrow function, the this
keyword is inherited from the parent scope and is not redefined, as shown below:const exampleObject = {
name: 'Example',
sayName: () => {
console.log(this.name); // Prints undefined
}
};
this
keyword refers to the global object because it is not redefined in the sayName
method.However, in a traditional function, the this
keyword is determined by how the function is called. It can be explicitly bound using the bind()
method, as shown below:const exampleObject = {
name: 'Example',
sayName: function() {
console.log(this.name);
}
};
const boundFunction = exampleObject.sayName.bind(exampleObject);
boundFunction(); // Prints Example
sayName
method is bound to the exampleObject
using the bind()
method, and the this
keyword refers to the exampleObject
.this
keyword can change based on how the function is invoked, which can lead to unexpected results. Let's look at some common scenarios:Global context: If a function is called without a context, the this keyword will refer to the global object (e.g., window in a web browser, global in Node.js).
Object method context: When a function is called as a method of an object, the this keyword refers to the object itself.
Constructor context: When a function is used as a constructor to create a new object, the this keyword refers to the new object being created.
Event context: In an event handler, the this keyword typically refers to the element that triggered the event.
Function context: If a function is called with the apply() or call() method, the this keyword is explicitly set to the first argument passed to those methods.