JavaScript Advance
/ 13 min read
Table of Contents
JavaScript Function Advanced
This section covers advanced function topics in JavaScript.
These chapters are best after you understand basic functions (calling, parameters, return values, expressions, and arrows).
Function Definitions
- Function Declarations
function functionName(parameters) { // code to be executed}Function Declaration refers specifically to a standalone statement that defines a named function using the function keyword. It is hoisted, meaning it is available throughout its scope before any code is executed
Function Definitions vs Function Declarations
Function declaration is one specific way to define a function.
Function Definition is a broader term that encompasses both function declarations and function expressions. It refers to the act of creating a function, including its name, parameters, and body. In practice, “function definition” may include:
Examples of function definitions include:
a. Function declarations
b. Function expressions
c. Arrow functions
Declarations vs Expressions
Function Expression assigns a function to a variable and may be anonymous:
const greet = function() { return "Hello!";};Functions are Objects
The typeof operator in JavaScript returns “function” for functions.
But, JavaScript functions can best be described as objects.
JavaScript functions have both properties and methods.
Function this
Q. What is this?
When the this keyword is used in a function, it refers to an Object.
Which Object, is not decided when the function is written.
The value of this is decided when the function is called.
- this in an Object Method
When a function is an object method:
this refers to the object that owns the method.
const person = { firstName: "John", lastName: "Doe", fullName: function() { return this.firstName + " " + this.lastName; }};
person.fullName();In the example above, this refers to the person object.
this.firstName means the firstName property of person.
this.firstName is the same as person.firstName.
- this in Event Handlers
In HTML event handlers, this refers to the HTML element that received the event:
<button onclick="this.innerHTML='Clicked!'">Click Me</button>- this in Arrow Functions
Arrow functions do not have their own this. They inherit this from the surrounding scope.
In regular functions the this keyword represented the object that called the function, which could be the window, the document, a button or whatever.
With arrow functions the this keyword always represents the object that defined the arrow function.
JavaScript Function call
The call() method can be used to call a function with a specific this.
The call() method lets an object use a method belonging to another object.
In this way, the same method can be used on different objects.
functionName.call(this, arg1, arg2, ...);call() vs Normal Function Call
function showName() { return this.name;}
const person = { name: "John" };
showName();showName.call(person);Without call(), this is not the person object.
With call(), this is set explicitly.
Function Apply
The apply() method lets you write a method that can be used on different objects.
The apply() method is used to call a function with a specific this.
The apply() method is similar to call(), but it passes arguments in an array.
functionName.apply(this, [arg1, arg2, ...]);- Using apply() to Set this
When you use apply(), you can decide what this should refer to.
const person1 = { name: "John" };const person2 = { name: "Paul" };const person3 = { name: "Ringo" };
function greet(greeting) { return greeting + " " + this.name;}
greet.apply(person3, ["Hello"]);
result :Hello RingoDifference Between call() and apply()
The only difference between apply() and call() is how arguments are passed.
The call() method takes arguments separately.
The apply() method takes arguments as an array.
greet.call(person, "Hello");greet.apply(person, ["Hello"]);Function bind
Like with call() and apply(), the bind() an object can borrow a method from another object.
Unlike call() and apply(), the bind() method does not run the function immediately.
Instead, it returns a new function that can be called later.
The new function remembers the this value you choosed.
const newFunction = functionName.bind(this, arg1, arg2, ...);- Using bind() to Fix this
The most common use of bind() is to make sure a function always uses the same this value.
const person1 = { name: "John" };const person2 = { name: "Paul" };const person3 = { name: "Ringo" };
function greet() { return "Hello " + this.name;}
const greetJohn = greet.bind(person1);
greetJohn();greetJohn is a new function that always uses person1 as this.
bind() vs call() and apply()
The difference between these methods is important:
a. call() calls a function immediately
b. apply() calls a function immediately
c. bind() returns a new function
- bind() for Functions Called Later
Without bind(), the this value may be lost.
const person = { name: "John", sayHello: function() { return "Hello " + this.name; }};
const hello = person.sayHello;hello(); // this is not personThe function above loses its this value.
- Using bind() for Preserving this
The bind() method can be used to prevent losing this.
In the following example, the person object has a display method.
In the display method, this refers to the person object:
const person = { firstName:"John", lastName: "Doe", display: function () { let x = document.getElementById("demo"); x.innerHTML = this.firstName + " " + this.lastName; }}
person.display();When a function is used as a callback, this is lost.
- bind() with Arguments
Arguments passed to bind() become fixed values.
This is sometimes called partial application.
function multiply(a, b) { return a * b;}
const double = multiply.bind(null, 2);
double(5);The double function will always multiply by 2.
Function Closer
JavaScript variables can belong to:
The local scope or The global scope
Global variables can be made local (private) with closures.
Closures makes it possible for a function to have “private” variables.
A closure is created when a function remembers the variables from its outer scope, even after the outer function has finished executing.
- Local Variables
A local variable is a “private” variable defined inside a function.
A function can access all variables in the local scope.
function myFunction() { let a = 4; return a * a;}- Global Variables
A global variable is a “public” variable defined outside a function.
A function can access all variables in the global scope:
let a = 4;function myFunction() { return a * a;}JavaScript Object Advanced
JavaScript Object Definitions
- Using an Object Literal
An object literal is a list of property key:values inside curly braces { }.
// Create an Objectconst person = { firstName: "John", lastName: "Doe", age: 50, eyeColor: "blue"};- JavaScript Object.create()
The Object.create() method creates an object from an existing object.
// Create an Object:const person = { firstName: "John", lastName: "Doe"};
// Create new Objectconst man = Object.create(person);man.firstName = "Peter";- JavaScript Object fromEntries()
The fromEntries() method creates an object from iterable key / value pairs.
const fruits = [["apples", 300],["pears", 900],["bananas", 500]];
const myObj = Object.fromEntries(fruits);- JavaScript Object.assign()
The Object.assign() method copies properties from one or more source objects to a target object.
// Create Target Objectconst person1 = { firstName: "John", lastName: "Doe", age: 50, eyeColor: "blue"};
// Create Source Objectconst person2 = {firstName: "Anne",lastName: "Smith"};
// Assign Source to TargetObject.assign(person1, person2);JavaScript Class Advanced
JavaScript Classes
- JavaScript Class Syntax
Use the keyword class to create a class.
Always add a method named constructor():
class Car { constructor(name, year) { this.name = name; this.year = year; }}- Using a Class
a. Normal Method
const myCar1 = new Car("Ford", 2014);const myCar2 = new Car("Audi", 2019);b. The Constructor Method
Always add a constructor() method.
Then add any number of methods.
class Car {
//constructor constructor(name, year) { this.name = name; this.year = year; } // method age() { const date = new Date(); return date.getFullYear() - this.year; }}
const myCar = new Car("Ford", 2014);document.getElementById("demo").innerHTML ="My car is " + myCar.age() + " years old.";JavaScript Class Inheritance
To create a class inheritance, use the extends keyword.
A class created with a class inheritance inherits all the methods from another class:
class Car { constructor(brand) { this.carname = brand; } present() { return 'I have a ' + this.carname; }}
class Model extends Car { constructor(brand, mod) { super(brand); this.model = mod; } show() { return this.present() + ', it is a ' + this.model; }}
let myCar = new Model("Ford", "Mustang");document.getElementById("demo").innerHTML = myCar.show();The super() method refers to the parent class.
By calling the super() method in the constructor method, we call the parent’s constructor method and gets access to the parent’s properties and methods.
- Getters and Setters
Classes also allow you to use getters and setters.
It can be smart to use getters and setters for your properties, especially if you want to do something special with the value before returning them, or before you set them.
To add getters and setters in the class, use the get and set keywords.
class Car { constructor(brand) { this.carname = brand; } get cnam() { return this.carname; } set cnam(x) { this.carname = x; }}
const myCar = new Car("Ford");
document.getElementById("demo").innerHTML = myCar.cnam;JavaScript Static Methods
Static class methods are defined on the class itself.
You cannot call a static method on an object, only on an object class.
class Car { constructor(name) { this.name = name; } static hello() { return "Hello!!"; }}
const myCar = new Car("Ford");
// You can call 'hello()' on the Car Class:document.getElementById("demo").innerHTML = Car.hello();
// But NOT on a Car Object:// document.getElementById("demo").innerHTML = myCar.hello();// this will raise an error.JavaScript Asynchronous Advanced
JavaScript Control Flow
Control Flow is the order in which statements are executed in a program.
By default, JavaScript runs code from top to bottom and left to right.
Control flow statements let you change that order, based on conditions, loops or keywords.
- Default Flow
Default flow executes code sequentially (from top to bottom / from left to right).
let x = 5;let y = 6;let z = x + y;
Flow sequentially: let x → let y → let z.- Conditional Control Flow
Conditions let you make decisions using:
ifif...elseswitchternary (? :)- Loops (Repetition Control Flow)
Loops let you run code multiple times using:
forwhiledo...while- Jump Statements
Jump statements let you change the flow abruptly using:
break - exits a loop or switchcontinue - skips the current loop iterationreturn - exits from a functionthrow - jumps to error handling- Function Flow
Functions are callable and reusable code blocks:
Function to compute the product of two numbers:
function myFunction(p1, p2) { return p1 * p2;}JavaScript Is Single-Threaded
JavaScript runs on a single thread.
It can only do one thing at a time.
Every task has to wait for the previous one to finish.
This can freeze an application during slow operations (like file requests).
Asynchronus Flow JavaScript Asynchronous Flow refers to how JavaScript handles tasks that take time to complete, like reading files, or waiting for user input, without blocking the execution of other code.
To prevent blocking, JavaScript can use asynchronous programming.
This allows certain operations to run in the background, and their results are handled later, when they are ready.
Callbacks
A callback is a function passed as an argument to another function
This technique allows a function to call another function
A callback function can run after another function has finished
- Function Sequence
JavaScript functions are executed in the sequence they are called. Not in the sequence they are defined.
This example will display “Hello”, but end up with “Goodbye” because the functions are called in that order:
function myFirst() { myDisplayer("Hello");}
function mySecond() { myDisplayer("Goodbye");}
myFirst();mySecond();- Sequence Control
Sometimes you would like to have better control over when to execute a function.
Suppose you want to do a calculation, and then display the result.
You could call a calculator function (myCalculator), save the result, and then call another function (myDisplayer) to display the result:
function myDisplayer(some) { document.getElementById("demo").innerHTML = some;}
function myCalculator(num1, num2) { let sum = num1 + num2; return sum;}
let result = myCalculator(5, 5);myDisplayer(result);- JavaScript Callbacks
Using a callback, you could call the calculator function (myCalculator) with a callback (myCallback), and let the calculator function run the callback after the calculation is finished:
function myDisplayer(some) { document.getElementById("demo").innerHTML = some;}
function myCalculator(num1, num2, myCallback) { let sum = num1 + num2; myCallback(sum);}
myCalculator(5, 5, myDisplayer);Q. When to Use a Callback?
The examples above are not very exciting.
They are simplified to teach you the callback syntax.
Where callbacks really shine are in asynchronous functions, where one function has to wait for another function (like waiting for a file to load).
Asynchronous functions are covered in the next chapter.
Asynchronous JavaScript
Functions running in parallel with other functions are called asynchronous.
Some tasks run in the background, and JS doesn’t wait for them to finish. Instead, it keeps going and comes back later when the task is done.
A good example is JavaScript setTimeout()
console.log("Start");
setTimeout(() => { console.log("Async task done");}, 1000);
console.log("End");
// consolesStartEndAsync task doneJavaScript Promises
A Promise in JavaScript is an object that represents the eventual result of an asynchronous operation — either a success (with a value) or a failure (with a reason). It lets asynchronous methods return values in a way that feels like synchronous code by allowing you to attach handlers for when the operation completes or fails.
A Promise can have 3 states:
a. Pending – initial state, not yet finished (no result yet).
b. Fulfilled – the operation finished successfully and produced a value.
c. Rejected – the operation failed and produced a reason (usually an error).
Creating a Promise (Promise Constructor)
const promise = new Promise((resolve, reject) => { // asynchronous work here if (successful) { resolve(result); // fulfills the promise } else { reject(error); // rejects the promise }});The constructor takes one argument: an executor function.
The executor function receives two callbacks:
resolve(value) — fulfills the promise with value.
reject(reason) — rejects the promise with reason.
resolve and reject are only available inside the executor.
Handling Promise Results
Once a promise is created, you attach handlers to deal with the result:
.then(onFulfilled, onRejected)
. Runs when promise fulfills or rejects.
. Optional second argument handles rejection.
. Returns a new promise, enabling chaining.promise.then( value => console.log("Result:", value), error => console.error("Error:", error));.catch(onRejected)
. Shortcut for handling only rejected cases.
. Equivalent to promise.then(undefined, onRejected).promise.catch(error => console.error("Caught error:", error));.finally(onFinally)
. Runs after the promise settles — whether it fulfilled or rejected.
. Useful for cleanup work (e.g., hiding a loading spinner).
. Always returns a new promise with the same outcome as the original.promise.finally(() => console.log("Done (either success or failure)"));Promise Chaining
because .then, .catch, and .finally all return new promises, you can chain them:
promise .then(step1) .then(step2) .catch(handleError) .finally(cleanUp);Static Promise Methods
These are methods on the Promise class (not on promise instances):
| Method | What it Does | |
|---|---|---|
Promise.all(iterable) | Waits for all promises to fulfill, or fails fast on first reject. | |
Promise.allSettled(iterable) | Waits until all settle, returns an array of results. | |
Promise.any(iterable) | Fulfills if any promise fulfills; rejects only if all reject. | |
Promise.race(iterable) | Settles as soon as the first promise settles. | |
Promise.resolve(value) | Returns a promise resolved with the value. | |
Promise.reject(reason) | Returns a promise rejected with the reason. | |
Promise.withResolvers() | Returns an object with a promise and its resolve/reject functions. |
JavaScript Asyn/Wait
“async and await make promises easier to write”
async makes a function return a Promise
await makes a function wait for a Promise
- Async Syntax
The keyword async before a function makes the function return a promise:
async function myFunction() { return "Hello";}- Await Syntax
The await keyword can only be used inside an async function.
The await keyword makes the function pause the execution and wait for a resolved promise before it continues:
let value = await promise;