Function expression is created when a variable is assigned a function.
assigned function can be without name (anonymous) like in the example above, or with name.
Function expressions are not hoisted, only the variable is hoisted.
// Function expression
var variableName = function ([parameters]) {
// Do something in here
}
Function declarations are hoisted.
// Function declaration
function functionName ([parameters]) {
// Do something in here
}
Arrow functions are not hoisted, only function declarations are.
// Arrow function ES6
var variableName = ([parameters]) => {
// Do something in here
}
Concise arrow function is used when the code to execute can be written in a single line. Concise arrow function doesn't have { }
brackets and we don't need to include keyword return
(it is implicit).
var variableName = ([parameters]) => /* expresion or statement */ ;
Functions by default return undefined
.
We have to use return
keyword to return the value from the function and avoid returning undefined
.
The return
keyword stops the execution, exits the function and returns the result.
function concatNames(fistName, lastName) {
console.log('before return');
return fistName + ' ' + lastName;
console.log('after return'); // This line will not run
}
var result = concatNames('John', 'Doe');
console.log('result: ' + result);
In Javascript we can pass functions as parameters to the function.
The function that is passed as an argument can be called back inside of the parent function.
A higher-order function is a function that can take another function as an argument, or that returns a **function **as a result.
Example:
In the below example startEatingDinner
is a Higher order function simply because it takes another function as argument.
eatDesert
is a function that is being passed as a callback, which is then invoked (called back) by the startEatingDinner
.
function eatDessert(){
console.log("Eating the dessert š°");
}
function startEatingDinner(callback){
console.log("Eating the dinner š½");
console.log("Finished eating dinner!");
callback();
}
startEatingDinner(eatDessert);
In the below code we call function sumNumbers
before declaring it, and it doesn't throw an error. Why ?
Function declarations are always hoisted to the top of the script by the engine during compilation, before the script runs.
sumNumbers(10, 50);
function sumNumbers (num1, num2) {
console.log(num1 + num2);
}
As well var
declarations are hoisted (but not initialized :) ).
Meaning that variable is created and hoisted before the script runs, but the value is not assigned.
console.log(cat); // undefined
var cat = 'Marshmallow';
console.log(cat); // Marshmallow
Remember :
ReferenceError: variable is not defined
is different than undefined
Scope is the context/area in which a variable or a function is visible from the different parts of the program.
In JavaScript there are different types of scope:
- Local scope
- Global scope
- Block scope (using
let
andconst
)
var myColor = "green"; // This is in the global scope
function myFunction() {
var firstName = 'John'; // This is in the local/function scope;
console.log('local scope - firstName -> ', firstName);
console.log('local scope - myColor -> ', myColor);
}
// myColor is accessible as it is a
console.log('Global - myColor -> ' + myColor);
// Not accessible because it firstName exists in the local scope of the function
console.log('Global - firstName -> ' + firstName);
// myFunction has acccess to both of the varabiles;
myFunction();
Changing the function arguments often creates a code that is hard to debug/maintain.
// BAD - changing the parameters invites bugs and creates bug prone code
function concatFullName(firstName, lastName) {
firstName = firstName + ' ' + lastName;
return firstName;
}
// GOOD
function concatFullName(firstName, lastName) {
var result = firstName + ' ' + lastName; // arguments are not tampered with
return result;
}