In JS functions are First-class functions because they are treated as any other variable. Remember that functions are objects.
- We can assign a function to a variable
- We can pass a function as an argument
- A function can return a function
When we call a function the first thing that happens is that a new execution context
is created with a thread of execution
(line by line) and a space in memory for storage. Whatever we store in memory in this local scope (aka, the context of the function) will be available JUST inside this context.
function sayHi() {
console.log('Hi');
}
sayHi(); // Hi
const sayHi = function() {
console.log('Hi');
}
sayHi(); // Hi
The main difference between function declaration
and function expression
is that WE CAN
call the function
defined with function declaration
before its definition.
This is because JS engine moves all the function declarations
to the top. This is called hoisting
.
You can see how sayHi()
is hoisted.
sayHi(); // Hi
function sayHi() {
console.log('Hi');
}
Quick note:
- If you use a name, like
const hi = function sayHi() {}
it is a named function expression. - If not, like
const hi = function() {}
it is an anonymous function expression.
The less parameters a function has, the better. So we should have default values in our functions.
function Person(name, age) {
this.name = name;
this.age = age;
// these are default properties hen we are creating the Person object
this.friends = [];
this.hobbies = [];
this.isAlive = true;
}
const peter = new Person('Peter', 30);
console.log(peter);
// Person {
// name: 'Peter',
// age: 30,
// friends: [],
// hobbies: [],
// isAlive: true,
// __proto__: { constructor: ƒ Person() }
// }
function sayHi(name = 'user') {
console.log(`Hi ${name}`);
}
sayHi();
sayHi('Peter');
// 'Hi user'
// 'Hi Peter'
We can have functions with a varying number of parameters...
- Using the rest operator (
parameter1, parameter2, ...args
) We will be looping through the args array.
function printNames(...args) {
for (let element of args) {
console.log(element)
}
}
printNames('Peter', 'Paul', 'Lora');
// 'Peter'
// 'Paul'
// 'Lora'
- Accessing the
argument
object.
function printNames() {
console.log(arguments);
}
printNames('Peter', 'Paul', 'Lora');
// {
// '0': 'Peter',
// '1': 'Paul',
// '2': 'Lora',
// length: 3,
// callee: ƒ printNames(),
// __proto__: {
// // ...
// }
// }
Loop through the arguments
keys:
function printNames() {
for (let key in arguments) {
console.log(arguments[key])
}
}
printNames('Peter', 'Paul', 'Lora');
// 'Peter'
// 'Paul'
// 'Lora'
Remember the difference between parameters
and arguments
In the example...
color
is aparameter
of the function printColor()black
is anargument
function printColor(color) {
console.log(color);
}
printColor('black');
A function that takes a function as argument or returns a function and can be assigned as a value to a variable.
More info: https://developer.mozilla.org/en-US/docs/Glossary/First-class_Function
function performMathOperation(num1, num2, operation) {
return operation(num1, num2);
}
function addition(num1, num2) {
return num1 + num2;
}
function subtraction(num1, num2) {
return num1 - num2;
}
const add = performMathOperation(1, 1, addition);
console.log(add); // 2
const subtract = performMathOperation(1, 1, subtraction);
console.log(subtract); // 0
Note: In the previous example performMathOperation()
is a HOF and addition()
is a callback function.