JAVASCRIPT INTERVIEW QUESTIONS

JAVASCRIPT -  JavaScript is a programming language used to create dynamic content for websites

Javascript is an object oriented scripting language

Java is an object oriented programming language

Is Java a scripting language? No Java is Not A Scripting Language its a Programming Language. For example, in the normal case, you have to compile a C program before you can run it. But in the normal case, you don't have to compile a JavaScript program before you run it

===========================================================================

Factors and reasons for UI performance issues:

  1. Excessive DOM Elements: Large numbers of DOM elements can slow down rendering and interactions 
  2. Large Assets: Heavy images, videos, and other media files can increase load times.
  3. Too Many Requests: Numerous HTTP requests can delay page loading.
  4. Redundant Styling: Redundant or unused CSS rules can increase stylesheet size.
  5. Mobile Responsiveness
  6. Third-Party Libraries:Heavy Dependencies: Large third-party libraries can slow down page loads.
  7. No Compression: Large files without compression can result in slow loading.

===========================================================================

Debugging is a critical skill for JavaScript developers to identify and resolve issues in their code. Here are some debugging techniques and tools that can help you effectively debug JavaScript code
  1. Console Logging:Use console.log() to print values and messages to the browser console. It's a simple way to track the flow of your code and view variable values.
  2. Browser Developer Tools
  3. Use the "Network" tab in developer tools to monitor network requests, their responses, and potential errors.




// Promises are objects are used to handle the asynchronous operation
// they provide then() method to handle fulfilled promises
// and a catch() method to handle rejections.

const handleTimeOutPromises = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('DONE.....');
}, 2000);
})
}

// handleTimeOutPromises().then((response) => { console.log(response) }).catch((error) => { console.log(error , 'error') });

const handleTimeOutFailurePromises = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('ERROR');
}, 2000);
})
}

// handleTimeOutFailurePromises().then((response) => { console.log(response) }).catch((error) => { console.log(error , 'error') });


Promise.all([handleTimeOutPromises(),handleTimeOutFailurePromises()]).then((response) => { console.log(response) }).catch((error) => { console.log(error , 'error') });

// Explanation:
// In the example above, Promise.all waits for handleTimeOutPromises, handleTimeOutFailurePromises to resolve.
// Once all are resolved, it returns a single promise that resolves with an array of the results.
// If any promise rejects, Promise.all immediately rejects with the reason of the first promise that rejected.


// Promise.race takes an iterable of promises and returns a single promise that resolves or rejects as soon as the first promise in the iterable resolves or rejects.

// Use Case: When you need the result of the first completed promise, regardless of whether it was resolved or rejected.

const promise1 = new Promise((resolve, reject) => { setTimeout(resolve, 500, 'one'); });

const promise2 = new Promise((resolve, reject) => { setTimeout(resolve, 100, 'two'); });

Promise.race([promise1, promise2]).then((value) => { console.log(value); }).catch((error) => { console.error(error); });// Output: "two"

// Promise.allSettled takes an iterable of promises and returns a single promise that resolves after all of the promises have settled, meaning each promise has either resolved or rejected. It never rejects, and it returns an array of objects describing the outcome of each promise.

// Use Case: When you want to know the result of all promises, whether they resolved or rejected, without short-circuiting on the first failure.

Promise.allSettled([handleTimeOutPromises(), handleTimeOutFailurePromises()]).then((results) => {
console.log(results, 'results');
});




// in javascript, closures are the inner function can access the outer function's variable
// its lexical scope
// They are commonly used for data encapsulation and maintaining state between function calls
// Closures are a fundamental concept in JavaScript

function outerFunction() {
let outerVariable = "Hey i am outside";
function innerFunction() {
return outerVariable; // Closures are The inner function can access the outer function's variable
}
return innerFunction();
}

const closures = outerFunction();
console.log(closures) // Hey i am outside




// What are the different data types in JavaScript?

// Answer: JavaScript supports the following data types:

// Primitive types: undefined, null, boolean, number, string, symbol, bigint.
// Non-primitive type: object (includes arrays, functions, and objects).

// Primitive Data Types
// ========================

// 1. undefined - Represents a variable that has been declared but not assigned a value.

let x;

console.log(x); // undefined

console.log(typeof x); // undefined

// 2.null - Represents the intentional absence of any object value.

let y = null;

console.log(y);

console.log(typeof y); // object

// 3.Boolean - Represents a logical entity and can have two values: true or false.

let isJavascriptFun = true;

console.log(isJavascriptFun);

console.log(typeof isJavascriptFun) // boolean

// 4. Number - Represents both integer and floating-point numbers.

let age = 25;
let price = 99.99;
console.log(age); // Output: 25
console.log(price); // Output: 99.99

// 5.String - Represents a sequence of characters, used to store and manipulate text.
let greeting = "Hello, World!";
console.log(greeting); // Output: "Hello, World!"


// 6.Symbol - Represents a unique identifier. Each Symbol is unique and immutable.

let sym = Symbol('id');

console.log(sym); // Symbol(id)

console.log(typeof sym); // symbol

// 7. BigInt - It is used for very large numbers that are beyond the safe integer limit in JavaScript

let bigNumber = BigInt(1234567890123456789012345678901234567890n);
console.log(bigNumber); // Output: 1234567890123456789012345678901234567890n


// Non-primitive type

// 1.Object
let person = {
name: "John",
age: 30,
isStudent: false
};
console.log(person.name); // Output: "John"

// 2.Array
let fruits = ["Apple", "Banana", "Cherry"];
console.log(fruits[1]); // Output: "Banana"

// 3.Function - A block of code designed to perform a particular task. Functions are objects in JavaScript.

function add(a, b) {
return a + b;
}
console.log(add(2, 3)); // Output: 5

// 4.Date - A built-in object used to work with dates and times.
let today = new Date();
console.log(today); // Output: current date and time

// Examples of Type Conversion

// JavaScript is a loosely typed or dynamic language,
// which means you don't have to specify the data type of a variable.
// It also allows type conversion, where a value of one type can be converted to another.

// 1.Implicit Conversion:
let num = "5" + 2;
console.log(num); // Output: "52" (String)

// 2.Explicit Conversion:
let num2 = "5";
let convertedNum = Number(num);
console.log(convertedNum); // Output: 5 (Number)


// var is function-scoped and can be redeclared or updated.
// let is block-scoped and can be updated but not redeclared in the same scope.
// const is block-scoped, and cannot be updated or redeclared once assigned.

// 1.var Example
// Scope: Function-scoped or globally-scoped.
// Hoisting: Variables declared with var are hoisted to the top of their scope but initialized with undefined.
// Re declaration: Can be re declared and updated.

function exampleVar() {
if (true) {
var message = "Hello"
}
console.log(message); // Hello
}
exampleVar();

var x = 10;
var x = 20; // Re declaration allowed
console.log(x); // Output: 20


// let Example
// Scope: Block-scoped.
// Hoisting: Variables declared with let are hoisted but not initialized (temporal dead zone).
// Re declaration: Cannot be re declared in the same scope, but can be updated.

function exampleLet() {
if (true) {
let message = "Hello"
}
// console.log(message) // ReferenceError: message is not define
}
exampleLet();

let y = 10;
y = 20; // Update allowed
console.log(y); // Output: 20

// let y = 30; // Error: Identifier 'y' has already been declared



// const Example
// Scope: Block-scoped.
// Hoisting: Variables declared with const are hoisted but not initialized (temporal dead zone).
// Re declaration: Cannot be re declared or updated in the same scope. Must be initialized at the time of declaration.


function exampleConst() {
if (true) {
const message = "Hello"
}
// console.log(message) // ReferenceError: message is not define
}

exampleConst();

const z = 10

// z = 20 // TypeError: Assignment to constant variable.

// const z = 30; // Error: Identifier 'z' has already been declared

console.log(z);


// An IIFE is a function that runs as soon as it is defined.
// It is written by placing the function inside parentheses followed by another set of parentheses to invoke it.

console.log((function welcomeMessage() {
return "Hello"
})()) // Hello


// Hoisting is a behavior in JavaScript where variable and function declarations are moved to the top of
// their containing scope during the compile phase, before code execution.

// Example 1: Variable Hoisting with var
console.log(a) // undefined
var a = 10;
console.log(a); // 10

var b;
console.log(b); // Output: undefined (because `a` is declared but not yet initialized)
b = 10; // Initialization happens here
console.log(b); // Output: 10


// Example 2: Function Hoisting

sayHello(); // Hello, world!
function sayHello() {
console.log("Hello, world!");
}

// In this example, the function sayHello is called before it is defined in the code.
// Due to hoisting, the entire function declaration is moved to the top of its scope,
// so the function can be called before it appears in the code.


// Example 3: Hoisting with let and const

// Variables declared with let and const are also hoisted, but they are not initialized.

//console.log(c) // ReferenceError: Cannot access 'c' before initialization

let c = 10

//console.log(d); // ReferenceError: Cannot access 'c' before initialization
const d = 30;

// Summary
// Variable hoisting with var: Variables declared with var are hoisted
and initialized with undefined.
// Function hoisting: Entire function declarations are hoisted,
allowing functions to be called before they are defined in the code.
// Hoisting with let and const: Variables are hoisted but are not initialized,
and accessing them before their declaration results in a ReferenceError
due to the temporal dead zone.


function debounce(func, delay) {
let timeoutId;

return function (...args) {

console.log('Debounced function triggered');

// Clear the previous timeout if the function is called again within the delay
clearTimeout(timeoutId);

// Set a new timeout to execute the function after the delay
timeoutId = setTimeout(() => {
console.log('Executing debounced function');
func.apply(this, args);
}, delay);
};
}

console.log(debounce())


===========================================================================

// How to Clone an Object in JavaScript?

// Example Object
const userDetails = {
name: "Stephen Prakash G",
age: 28,
verified: false,
hobbies: ["reading", "coding"]
};
// Method 1: Spread Operator (Shallow Clone)
const clone1 = { ...userDetails };
// Method 2: Object.assign() (Shallow Clone)
const clone2 = Object.assign({}, userDetails);
// Method 3: JSON.parse() and JSON.stringify() (Deep Clone)
const clone3 = JSON.parse(JSON.stringify(userDetails));
// Modifying clones to demonstrate immutability
clone1.name = "John Doe";
clone2.age = 30;
clone3.verified = true;
clone1.hobbies.push("gardening"); // This should not modify the original array due to shallow copy
// Output the clones and original object to see changes
console.log("Original Object:");
console.log(userDetails);
console.log("\nClones:");
console.log(clone1);
console.log(clone2);
console.log(clone3);
/*
Output:
Original Object:
{
name: 'Stephen Prakash G',
age: 28,
verified: false,
hobbies: [ 'reading', 'coding' ]
}
Clones:
{
name: 'John Doe',
age: 28,
verified: false,
hobbies: [ 'reading', 'coding', 'gardening' ]
}
{
name: 'Stephen Prakash G',
age: 30,
verified: false,
hobbies: [ 'reading', 'coding' ]
}
{
name: 'Stephen Prakash G',
age: 28,
verified: true,
hobbies: [ 'reading', 'coding' ]
}
*/
// Conclusion: Methods 1 and 2 create shallow clones, where nested objects or arrays are
// still referenced.
// Method 3 creates a deep clone, ensuring complete immutability.

// Method 1 (Spread Operator) and Method 2 (Object.assign()): Both create shallow clones. //Modifying nested properties
// like hobbies in the clone affects the original object due to reference sharing.
// Method 3 (JSON.parse() and JSON.stringify()): Creates a deep clone. Modifying properties
// in this clone does not affect the original object because a new object and array are created.

Post a Comment

Previous Post Next Post