Functions
Functions are JavaScript codes that you declare once and can be called (invoked) multiple times. A function that is attached to an object or a class is also called the method of that object or class.
- When you declare a function, you can specify their parameters, which behave like local variables of the function whose value will be decided when you call the function.
- When you call a function, you provide the values (arguments) for the parameters.
- You may use the
returnkeyword inside a function to return a value (exit the function with the given value).
Creating a function
You can create a "normal" function (using the function keyword) or an "arrow" function (using the => notation).
Using the function keyword
You may provide the name of the function after the function keyword, before the open paranthesis. This name of the function becomes a local variable inside the function itself, which you can call again, creating a recursive function ("a function that calls itself").
You can provide the parameters between the ( and ), separated by ,.
function factorial(n) {
if (n === 0 || n === 1) {
return 1;
}
return n * factorial(n - 1);
}
console.log(factorial(5)); //=> 120 = 5!Using the => notation
On the left-hand side of =>, you put:
- the list of parameters — if there is only one parameter, you can omit the
().
On the right-hand side of =>, you put:
- a block of statements to run (using
{}), OR - a value to return (e.g.,
x => x + 1is a shorthand of(x) => { return x + 1 }). Due to ambiguous syntax, if you want to immediately return an object, make sure to wrap it with(), e.g.x => ({ value: x })
const arr = [1, 2, 3];
arr.forEach((el, index) => {
console.log(`arr[${index}] = ${el}`);
});Using new Function
You can also create a function from a string of JavaScript code using new Function(...parameterNames, functionBody). The scope for functionBody would be the global scope.
const f = new Function('x', 'y', 'return x + y');
console.log(f(2, 5)); //=> 7Function parameters
Parameter's default value
By using = after a parameter's name, you can assign the default value for that parameter.
function logMessage(greetings = 'Hello', name = 'user') {
console.log(greetings + ', ' + name + '!');
}
logMessage('Hi'); //=> Hi, user!Rest parameters
By using the spread operator (...), you can make your function receive any number of arguments.
function testFn(a, b, ...rest) {
console.log(a); //=> 1
console.log(b); //=> 2
console.log(rest); //=> [3, 4, 5]
}
testFn(1, 2, 3, 4, 5);Invoking functions
As a function
Use the () operator to call the function, specifying inside it the list of arguments.
function total(a, b, ...rest) {
console.log(a); //=> 1
console.log(b); //=> 2
console.log(rest); //=> [3, 4, 5]
}
testFn(1, 2, 3, 4, 5);You can also use the spread operator (...) to "spread" an iterable (e.g. an array or a string) into "comma-separated values" for the arguments.
const arr = [];
const numbers = [1, 2, 3];
// This is equivalent to:
// arr.push(1, 2, 3);
arr.push(...numbers);
As a constructor
You can call a function as a constructor using the new keyword, specifying inside it the list of arguments. (You can also use the spread operator as mentioned above.)
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
const person = new Person('James', 'Smith');
console.log(person);A constructor function typically does not use the return keyword, and it returns the object being created. If you use a return, though:
- if you return a primitive value, it is ignored (it still returns the object being created)
- if you return an object, then it becomes the resolved value of the invocation expression
Indirectly using .apply() or .call()
You can use the following to indirectly call a function:
functionName.apply(thisArg, argsArray), orfunctionName.call(thisArg, ...args)
Using these allows you to override the this value received by your function.
function greetUser(menuA, menuB) {
console.log('Hello, ' + this.firstName + ' ' + this.lastName + '.');
console.log('Do you want ' + menuA + ' or ' + menuB + '?');
}
const user = { firstName: 'Joe', lastName: 'Lamy' };
// `user` will become `this` inside `greetUser`
greetUser.apply(user, ['coffee', 'tea']); // "A is for array"
greetUser.call(user, 'coffee', 'tea'); // "C is for comma"To help you remember
- Apply expects an array ("A is for array")
- Call expects comma-separated values ("C is for comma")
Special variables
this
Non-arrow functions have this variable defined inside it. The value depends on how you call a function. You can override it by using bind, apply, or call when calling a function.
- If you call a function as a function —
thiswill be the global object (globalThis) while not in strict mode, andundefinedwhile in strict mode. - If you call a function as a method of an object —
thiswill be the object on which you call the function.
Arrow functions do not have their own this variable, so they inherits this variable from their enclosing scope. (Sometimes a useful feature of arrow functions.)
arguments
Non-arrow functions have arguments variable defined inside it. It behaves like an array, but it only has the length property (apart from its elements).
This was the only way to create functions that accept any number of arguments ("varargs functions") before rest parameters was introduced in ES6. You should just use rest parameters in modern JavaScript.
function sum() {
let total = 0;
for (let i = 0; i < arguments.length; i++) {
total += arguments[i];
}
return total;
}
console.log(sum(4, 5, 6)); //=> 15
console.log(sum(1, 4, 7, 9)); //=> 21The function instance
When you have a function instance (let's call it fn), it has the following properties/methods.
Properties
fn.name
The name of the function.
fn.length
The number of parameters of the function, NOT including rest parameters.
function func1() {}
function func2(a, b, c, d, ...z) {}
console.log(func1.length); //=> 0
console.log(func2.length); //=> 4Methods
fn.apply(thisArg, argsArray)
Calls function fn with the given this value and array of arguments.
fn.call(thisArg, ...args)
Calls function fn with the given this value and comma-separated arguments.
fn.bind(thisArg, ...args)
Creates a new function that when called has this value of thisArg (required), and its first parameters are ...args (optional).
(The latter behavior of bind is akin to partial application or currying in functional programming.)
let add = (x, y) => x + y;
let boundAdd = add.bind(null, 1);
console.log(boundAdd(2)); //=> 3 (1 + 2 = 3)References
- JavaScript: The Definitive Guide, 7th Edition (David Flanagan) — Chapter 8. Functions
- The arguments object — https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments
- this — https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
- Function.name — https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name
- Function.length — https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length