JavaScript Tutorial
indexjavascript history javascript versions environment setup variables and data typesOperatorsstrings and numbers programming constructs arrays built in objects functions objects call apply bind closures error handling debugging CallbacksJS in Browser
BOM and DOMBrowser EventsWeb APIAjaxJQueryMost popular librariesAdvanced
prototypes Object Oriented ProgrammingModulesAsynchronous programmingBinary DataInternationalizationreactangularjsProjectsMiscellaneous
typescriptJS ecosystemChrome dev toolstesting frameworksInterview questions and AnswersFunctions in JavaScript
Important points to note about functions are given below- functions are object
- this and arguments objects are available for functions
- There are mainly 2 types of functions - named and anonymous
- Function can return a value
- Primitive types of parameters are passed to function by value
- Reference type of Parameters are passed to function by reference
- We can also set the default parameter to function
- ... notation can be used to mark the variable length parameter
Function definition Examples
//standard functions
function calculate(){
console.log("calculate something")
}
calculate();
//Assigning function to variable.
let f1 = function calculate(){
console.log("calculate something")
}
f1();
Function Parameters Examples
Below examples show how to pass the parameters to JavaScript functions. We have also demonstrated how to set default parameter and variable number of parameters.
//Passing param
function add(a,b){
return a + b;
}
let result = add(2,3)
console.log(result) // output - 5
//Default param
function addDefault(a,b=2){
return a + b;
}
result = addDefault(4)
console.log("Default param addition - > " + result) // output - 6
//Variable number of params
function addVariableParams(...a){
let result = 0;
for(let i=0;i<a.length;i++){
result += a[i];
}
return result;
}
result = addVariableParams(4,5,7,5)
console.log("Variable param addition - " + result) // output - 21
//simple procedural function
function add(a,b){
// In function, "this" may refer to different objects based on how it is called
// e.g. It may refer to global object, f1.call(newThis) or e.addEventListener("event", f1);
// In the top-level code in a Node module, this is equivalent to module.exports.
console.log('this in function -> ', this);
return a+b
}
console.log("Sum of 1,2 -> ", add(1,2)); // this will point to globalThis
let o1 = {x:10}
add.call(o1) // this will point to o1
//Arguments
function f1(a, b, c) {
//arguments object is not an instance of Array
console.log(arguments[0]);
console.log(arguments[1]);
console.log(arguments[2]);
//before rest syntax, we have to use below ways to convert arguments into Array
//let a = Array.prototype.slice.call(arguments)
//let a = [].slice.call(arguments)
//let a = Array.from(arguments)
}
f1(1, 2, 3);
//variadic functions
function f2(...theArgs) {
//theArgs is a real array
console.log(theArgs);
}
console.log(f2(1, 2, 3));
console.log(f2(1, 2, 3, "s"));
//Only the last parameter in a function definition can be a rest parameter.
function f3(a,b,...args) {
}
Factory functions
Factory functions are used to build and return the objects.
//factory function
function getFactoryObjects(name){
console.log('this in factory function -> ', this);
return {
"name": name
}
}
let f5 = getFactoryObjects("sagar")
// this refers to globalThis like a normal function
Constructor Function
Constructor function are used to create objects using new operator When called with new operator, "this" refers to the new object that is created.
function User(name){
this.name = name
this.printName = function(){
console.log('this in cons function and Name is -> ', this, this.name);
}
}
let u1 = new User("sagar")
u1.printName();
// using Function constructor
const addFunction = new Function('a', 'b', 'return a + b');
console.log('Function const output ' , addFunction(2, 2));
//Function expression
let f8 = function (){
console.log('This is a function expression');
}
f8();
Arrow functions - Lambda Functions
- lambda functions or arrow functions - call, apply, bind does not work
- lambda functions does not have prototype
- "this" is lexically bound in lambda. In normal functions, this refers to object that called the function.
- call() and apply() will not be able to provide another value for "this"
- There is is no arguments variable inside lambda
- Arrow function does not have its own bindings to this or super, and should not be used as methods.
- Arrow function can not be used as constructors
- Arrow function can not use yield, within its body
//fat arrow syntax
p = () => {console.log("fat arrow syntax")}
p()
let lambda = () => console.log('this here in lamda refers to module.exports->', this);
console.log('typeof l', typeof lambda);
lambda.call(u1); // ignores the object passed
IIFE - Immedietly invoked function expression - Anonymous functions
- main benefit is that it does not pollute global scope. Useful to hide/protect data like private members in Java
- used in most of old libraries like JQuery
- If you want to expose some objects, you can use return statement from IIFE
//anonymous functions - IIFE - call, apply bind does not work
(function x(){
console.log("IIEF")
})();
let getDiscount = (function x(){
let discount = 20
return function(b){
return b-(b*discount/100)
}
})();
console.log(getDiscount(888))
//error discount can not be accessed
console.log(discount)
Closure
- closure = function + lexical environment
- benefits - memeory efficient and encapsulation
- To add encapsulation, do not return those objects/functions from the function You should return (expose) only those things that you want to make publicly accessible
- do not pollute global space
- It's memory efficient because closure can access the heap that was created before. We can access old heap and reference it again and again
- a function remembers where it was born in the special property [[Environment]]. It references the Lexical Environment from where it’s created
let f1 = function (index){
//each function call will create new array object and store on heap
let a = new Array(777).fill("dddd")
console.log("invoked")
return a[index]
}
console.log(f1(2))
//with closure, we can persist the lexical environment meaning Array is created only once.
// In subsequent calls, we can refer same array from within closure
let f1 = function (){
let a = new Array(777).fill("dddd")
console.log("invoked")
return function (index){
return a[index]
}
}
let x = f1();
console.log(x(2))
Currying
function multiply(a,b){
return a*b;
}
let multiplybyseven = multiply.bind(this,7)
console.log(multiplybyseven(10))
//result will be 7*10 = 70
//this is called as currying
Web development and Automation testing
solutions delivered!!