1. what is closure
ES5 has three kind of scope 1st global 2nd functional leval 3rd is closure. it says that variable created inside outer function can be used inside inner function.
Benefits:
- we can create private variable by using it.
- we can create closure for async methods if they are in loop.
Cons:
- since scope of variable keeps alive they are not getting garbase collected so more memory uses will be there.
2. what variable and function hoisting, and what are differences between them.
variable defined or created anywhere in scope there definition goes on top is termed as variable hoisting.
function defined or created anywhere in scope there definition and implementation too goes on top is termed as function hoisting.
3. what is difference between var, let, const
var : used for variable creation and has only three scope global,functional, closure.
let : used for variable creation but its scope is valid inside block only variable created by using it can be registered for GC(garbage collection) after coming out of the block.
const : used for variable creation and is similar as final in java once initialised can not change its value.
4. what is difference between call, apply and bind
these all method are being used for attaching the context(value of this
) but bind does not expect any
argument where call expect object of argument and apply expect array of argument.
When I'm not having any argument I'll use bind. when I'm not certain for the length of argument I'll use apply else if I know all argument I'll use call.
5. what is promise.
6. Answer:
A promise is used to track a task which will execute in future and can go in two phases e.g. resolved/rejected
For other part search google.
7. what all http method are there and their significance
Get: It is being used to fetch the data. Post: We use it when we want to send some data to server and want something in return. Put: It is being just to put some data on server. delete: It is being used to delete some data on server. Option: For other purpose we use it like validating tokens etc.
Note: These are just for standards. We are not strictly bound to use them for given purpose.
8. what is the output of following code and how you will rectify it
for(var i = 0; i<100;i++){
setTimeout(function(){
console.log(i);
},1000);
}
It will print 100 hundred times because loop will get executed initially and callback passed to setTimeout method will
be pushed to the end of event loop. so they will executed when i
will be already set to its limit i.e.
100
We can reactify it in following ways:
-
Using closure
for(var i = 0; i<100;i++){ (function(i){ setTimeout(function(){ console.log(i); },1000); })(i) }
-
Using let keyword ```javascript for(let i = 0; i<100;i++){ setTimeout(function(){
},1000); }console.log(i);
- Using call/apply
```javascript
// search google
9. what is major difference between ECMA5 and ECMA6
See link (http://es6-features.org/#Constants)
Classes, Arrow Functions, Block Scope using let keyword, Promises etc
10. what is ECMA
ECMA is an organisation which standardise javascript.
11. Why javascript is your favorite language
It is my favorite language because of its simplicity and diversity to use. If I know javascript I can work on any part of application Front-End(react, angular etc.), TDD testing(kerma, mocha, chai), BDD testing(protractor), backend or micro-services using nodeJS, DataBase in MongoDB, IOT or embeded system using jerryscript etc.
12. what is callback hell and how you will remove it
long or iterative nesting of asynchronous functions is known as callback hell.
We can remove it in two ways:
- By using promises
- By using async await
13. what is anonymous functions?
An anonymous function is a function without a name. It is defined on the fly, often used for short, one-time operations. In JavaScript, you can create anonymous functions using the function keyword without assigning a name.
14. what is prototype
n JavaScript, a prototype is an object from which other objects inherit properties and methods. It serves as a template or blueprint for creating objects with shared characteristics. Objects in JavaScript have an implicit reference to their prototype, and when a property or method is accessed on an object, JavaScript looks for it in the object's prototype chain if it's not found directly on the object. The prototype mechanism enables the concept of prototypal inheritance, allowing objects to inherit and share behavior.
15. What all ways we can implement OOPS(Object Oriented Programming System) like inheritance, encapsulation, Polymorphism, abstraction. what is prototypical inheritance
In JavaScript, which is a prototype-based language, you can implement Object-Oriented Programming (OOP) principles such as inheritance, encapsulation, polymorphism, and abstraction. Here's a brief explanation of each with examples:
16. Inheritance:
-
Definition: Inheritance is the ability of a class (or object) to inherit properties and methods from another class (or object).
-
Example:
javascript// Parent class function Animal(name) { this.name = name; } // Child class inheriting from Animal function Dog(name, breed) { Animal.call(this, name); // Call the constructor of the parent class this.breed = breed; } // Creating an instance of the child class const myDog = new Dog('Buddy', 'Labrador'); console.log(myDog.name); // Accessing property from the parent class
17. Encapsulation:
-
Definition: Encapsulation is the bundling of data and methods that operate on the data into a single unit, restricting access to some of the object's components.
-
Example:
javascript// Using closures for encapsulation function Counter() { let count = 0; // Private variable return { increment: function() { count++; }, getCount: function() { return count; } }; } const myCounter = Counter(); myCounter.increment(); console.log(myCounter.getCount()); // Accessing data through methods
18. Polymorphism:
-
Definition: Polymorphism allows objects of different types to be treated as objects of a common type, enabling flexibility and extensibility.
-
Example:
javascript// Polymorphic function function printInfo(animal) { console.log(`Name: ${animal.name}`); if (animal.speak) { animal.speak(); } } // Objects with a common interface const cat = { name: 'Whiskers', speak: function() { console.log('Meow'); } }; const dog = { name: 'Buddy', speak: function() { console.log('Woof'); } }; printInfo(cat); printInfo(dog);
19. Abstraction:
-
Definition: Abstraction is the process of simplifying complex systems by modeling classes based on essential properties and behaviors.
-
Example:
javascript// Abstracting a Shape class class Shape { constructor(color) { this.color = color; } // Abstract method draw() { throw new Error('Abstract method - implement in subclasses'); } } // Concrete implementation class Circle extends Shape { constructor(color, radius) { super(color); this.radius = radius; } draw() { console.log(`Drawing a ${this.color} circle with radius ${this.radius}`); } } const myCircle = new Circle('red', 5); myCircle.draw();
These examples illustrate how you can implement OOP principles in JavaScript. It's important to note that JavaScript's approach to OOP is prototype-based, and the language provides flexibility in achieving OOP concepts. ES6 and later versions have introduced class syntax, making it more familiar to developers coming from class-based languages.
20. what is prototype chain
In JavaScript, the prototype chain is a mechanism that allows objects to inherit properties and methods from other objects through their prototype. Each object in JavaScript has an implicit reference to its prototype, forming a chain of objects linked together. When you access a property or method on an object, and if it's not found directly on the object, JavaScript looks for it in the object's prototype, and this process continues up the prototype chain until the property or method is found or the chain reaches the end.
Here's a basic explanation of the prototype chain:
-
Objects and Prototypes:
- Every object in JavaScript is associated with a prototype object.
- The prototype object is another object that the current object inherits from.
-
Accessing Properties and Methods:
- When you try to access a property or method on an object, JavaScript checks if the object has that property or method.
- If the property or method is not found on the object, JavaScript looks for it in the object's prototype.
-
Chain of Inheritance:
- If the property or method is not found in the immediate prototype, JavaScript continues searching up the prototype chain.
- This forms a chain of objects linked by their prototypes.
-
Prototype of Prototypes:
-
The process continues until the end of the prototype chain, where the last prototype typically has a
null
prototype. -
If the property or method is not found anywhere in the prototype chain, JavaScript returns
undefined
.
-
The process continues until the end of the prototype chain, where the last prototype typically has a
Here's a simple example to illustrate the prototype chain:
javascript// Parent object
const animal = {
eat: function() {
console.log('Eating...');
}
};
// Child object inheriting from the parent
const dog = Object.create(animal);
dog.bark = function() {
console.log('Barking...');
};
// Grandchild object inheriting from the dog
const puppy = Object.create(dog);
puppy.wagTail = function() {
console.log('Wagging tail...');
};
// Accessing properties/methods along the prototype chain
puppy.wagTail(); // Found on puppy
puppy.bark(); // Found on dog (inherited from animal)
puppy.eat(); // Found on animal (inherited from Object.prototype)
In this example, puppy
inherits from dog
, which in turn inherits from animal
,
forming a prototype chain. The Object.create()
method is used to create objects with a specified
prototype.
21. what is difference between arrow functions and normal/regular functions
Arrow functions and regular (or normal) functions in JavaScript have some key differences in terms of syntax,
behavior, and the handling of the this
keyword. Here are the main distinctions:
22. Syntax:
-
Arrow Function:
javascript
const add = (a, b) => a + b;
-
Regular Function:
javascript
function add(a, b) { return a + b; }
23.
this
Binding:
-
Arrow Function:
-
Arrow functions do not have their own
this
context. They inherit thethis
value from the enclosing scope (lexical scoping). - This behavior can be advantageous in certain scenarios, especially when dealing with callbacks and maintaining the context.
-
Arrow functions do not have their own
-
Regular Function:
-
Regular functions have their own
this
context, which is dynamically determined at runtime based on how the function is called. -
The
this
value in a regular function is influenced by how the function is invoked, such as with methods, constructors, or standalone function calls.
-
Regular functions have their own
24. Arguments Object:
-
Arrow Function:
-
Arrow functions do not have their own
arguments
object. If you need to access arguments, you would use thearguments
object of the enclosing scope.
-
Arrow functions do not have their own
-
Regular Function:
-
Regular functions have their own
arguments
object, which contains all the arguments passed to the function.
-
Regular functions have their own
25.
new
Keyword:
-
Arrow Function:
-
Arrow functions cannot be used as constructors. They cannot be invoked with the
new
keyword to create instances.
-
Arrow functions cannot be used as constructors. They cannot be invoked with the
-
Regular Function:
-
Regular functions can be used as constructors when invoked with the
new
keyword, allowing the creation of new objects.
-
Regular functions can be used as constructors when invoked with the
26.
prototype
Property:
-
Arrow Function:
-
Arrow functions do not have a
prototype
property. They cannot be used as constructors, so there is no prototype for instances.
-
Arrow functions do not have a
-
Regular Function:
-
Regular functions have a
prototype
property, which is used when creating instances with thenew
keyword. Instances inherit properties and methods from the prototype.
-
Regular functions have a
27. Example:
Here's a practical example demonstrating the this
behavior:
javascriptconst obj = {
value: 42,
getValueArrow: () => this.value,
getValueRegular: function() {
return this.value;
}
};
console.log(obj.getValueArrow()); // undefined (lexical scoping)
console.log(obj.getValueRegular()); // 42 (this is obj)
In the arrow function getValueArrow
, this
refers to the global object or
undefined
(in strict mode) because arrow functions do not bind their own this
. In contrast,
the regular function getValueRegular
correctly refers to the value
property of the
obj
.
In summary, the choice between arrow functions and regular functions depends on the specific use case, especially when
considering the handling of this
and other factors. Arrow functions are concise and often preferred for
short, simple functions, while regular functions provide more flexibility and are suitable for a wider range of
scenarios.
28. what is difference between function expression and function keyword
The terms "function expression" and "function keyword" refer to different ways of defining functions in JavaScript. Here are the key differences:
29. Function Expression:
- In a function expression, a function is assigned to a variable. It's a type of variable assignment where the function is part of an expression.
- Function expressions are often used for anonymous functions or when a function is only needed in a specific context.
-
Example:
javascript
const add = function(a, b) { return a + b; };
30. Function Keyword:
-
The "function keyword" typically refers to the traditional way of defining a function using the
function
keyword followed by the function name and a block of code. -
Function declarations using the
function
keyword are hoisted, meaning they are moved to the top of their scope during the compilation phase. -
Example:
javascript
function add(a, b) { return a + b; }
31. Key Differences:
-
Hoisting:
- Function expressions are not hoisted. They are only available in the code after the point of declaration.
-
Function declarations using the
function
keyword are hoisted, meaning they can be used in the code before the declaration.
-
Anonymous vs Named:
- Function expressions can be anonymous (no function name) or named.
-
Function declarations using the
function
keyword are named by default, but they can also be anonymous.
-
Usage:
- Function expressions are often used when a function is assigned to a variable, passed as an argument, or used in a specific context.
- Function declarations are typically used when you need the function to be available throughout the scope, and you want it to be hoisted.
-
Hoisting Order:
- The assignment part of a function expression is not hoisted, only the variable declaration is hoisted.
- The entire function declaration (including its body) is hoisted.
32. implement promise, apply, call, bind using es5 (Very important for senior software engineer)
In ES5 (ECMAScript 5), which is the version of JavaScript released in 2009, Promise
, apply
,
call
, and bind
were not native features. However, you can create your own implementations
for some of these functionalities. Note that the examples provided here are simplified and might not cover all the
edge cases handled by the native implementations in modern JavaScript.
33. Promise (Deferred Pattern):
javascriptfunction MyPromise() {
this.state = 'pending';
this.value = undefined;
this.callbacks = [];
this.resolve = function(value) {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.callbacks.forEach(callback => callback.onFulfilled(value));
}
};
this.reject = function(reason) {
if (this.state === 'pending') {
this.state = 'rejected';
this.value = reason;
this.callbacks.forEach(callback => callback.onRejected(reason));
}
};
this.then = function(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
if (this.state === 'fulfilled') {
setTimeout(() => {
try {
const result = onFulfilled(this.value);
resolve(result);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.state === 'rejected') {
setTimeout(() => {
try {
const result = onRejected(this.value);
resolve(result);
} catch (error) {
reject(error);
}
}, 0);
} else {
this.callbacks.push({ onFulfilled, onRejected, resolve, reject });
}
});
};
}
// Example usage:
const promise = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('Success!');
// or
// reject('Failure!');
}, 1000);
});
promise.then(
result => console.log('Fulfilled:', result),
error => console.error('Rejected:', error)
);
34. apply, call, bind:
In ES5, you can implement basic versions of apply
, call
, and bind
as follows:
javascript// Polyfill for Function.prototype.apply
Function.prototype.myApply = function(context, argsArray) {
context = context || global; // global object if context is undefined or null
context.__fn = this;
const result = context.__fn(...argsArray);
delete context.__fn;
return result;
};
// Polyfill for Function.prototype.call
Function.prototype.myCall = function(context, ...args) {
context = context || global;
context.__fn = this;
const result = context.__fn(...args);
delete context.__fn;
return result;
};
// Polyfill for Function.prototype.bind
Function.prototype.myBind = function(context) {
const fn = this;
const args = Array.prototype.slice.call(arguments, 1);
return function() {
const bindArgs = Array.prototype.slice.call(arguments);
return fn.apply(context, args.concat(bindArgs));
};
};
// Example usage:
function greet(greeting) {
console.log(`${greeting}, ${this.name}!`);
}
const person = { name: 'John' };
greet.myApply(person, ['Hello']); // Output: Hello, John!
greet.myCall(person, 'Hi'); // Output: Hi, John!
const boundGreet = greet.myBind(person, 'Hola');
boundGreet(); // Output: Hola, John!
Keep in mind that these implementations are basic and may not cover all edge cases and features of the native implementations in modern JavaScript. For production use, it is recommended to use the native methods or consider using a transpiler like Babel to write modern JavaScript code that can be transpiled to ES5 for wider compatibility.
35. what is rest parameters
Rest parameters in JavaScript allow you to represent an indefinite number of arguments as an array. They are
introduced using the ellipsis (...
) followed by a parameter name, and they gather the remaining arguments
passed to a function into an array. Rest parameters provide a concise way to work with variable-length argument lists.
Here's a basic syntax example:
javascriptfunction sum(...numbers) {
return numbers.reduce((acc, num) => acc + num, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // Output: 15
In this example, the sum
function takes any number of arguments and uses the rest parameter
...numbers
to gather them into an array called numbers
. The function then uses the
reduce
method to calculate the sum of all the numbers in the array.
Key points about rest parameters:
-
Syntax:
- Rest parameters are indicated by the use of the ellipsis (
...
) followed by a parameter name. - The rest parameter must be the last parameter in the function's parameter list.
- Rest parameters are indicated by the use of the ellipsis (
-
Array Representation:
- The rest parameter collects the remaining arguments into an array.
-
No Need for
arguments
Object:-
Rest parameters provide a more convenient and modern alternative to using the
arguments
object, which is an array-like object available in all function scopes that holds all passed arguments.
-
Rest parameters provide a more convenient and modern alternative to using the
-
Use Cases:
- Useful when dealing with functions that accept a variable number of arguments.
- Simplifies handling variable-length argument lists without explicitly specifying each parameter.
-
Example with Regular Parameters:
javascriptfunction example(a, b, ...rest) { console.log(`a: ${a}`); console.log(`b: ${b}`); console.log(`rest: ${rest}`); } example(1, 2, 3, 4, 5); // Output: // a: 1 // b: 2 // rest: 3,4,5
Rest parameters are widely used in modern JavaScript to enhance the flexibility and readability of functions that work with variable-length argument lists. They are especially handy when dealing with functions where the number of arguments may vary.
36. what is destructuring in javascript
Destructuring in JavaScript is a concise and flexible syntax that allows you to extract values from arrays or properties from objects and assign them to variables. It provides a more convenient way to work with structured data, making code shorter and more readable.
37. Array Destructuring:
With array destructuring, you can extract values from an array and assign them to variables in a single statement:
javascript// Example 1
const numbers = [1, 2, 3];
const [a, b, c] = numbers;
console.log(a, b, c); // Output: 1 2 3
// Example 2: Skipping values
const [first, , third] = numbers;
console.log(first, third); // Output: 1 3
38. Object Destructuring:
With object destructuring, you can extract values from an object and assign them to variables with matching property names:
javascript// Example 1
const person = { name: 'John', age: 30, city: 'New York' };
const { name, age, city } = person;
console.log(name, age, city); // Output: John 30 New York
// Example 2: Assigning to new variable names
const { name: fullName, age: years, city: residence } = person;
console.log(fullName, years, residence); // Output: John 30 New York
39. Default Values:
You can also provide default values for variables in case the value is not present:
javascriptconst colors = ['red', 'green'];
const [primary = 'blue', secondary = 'yellow', tertiary = 'purple'] = colors;
console.log(primary, secondary, tertiary); // Output: red green purple
40. Nested Destructuring:
Destructuring can be nested for more complex data structures:
javascriptconst person = { name: 'John', age: 30, address: { city: 'New York', zip: '10001' } };
const { name, address: { city } } = person;
console.log(name, city); // Output: John New York
41. Function Parameter Destructuring:
You can use destructuring in function parameters:
javascriptfunction printPerson({ name, age }) {
console.log(`Name: ${name}, Age: ${age}`);
}
const person = { name: 'Alice', age: 25 };
printPerson(person); // Output: Name: Alice, Age: 25
Destructuring simplifies code, especially when working with complex data structures, and is widely used in modern JavaScript to make code more readable and maintainable. It's supported in ES6 (ECMAScript 2015) and later versions of JavaScript.
42. what are generator functions in javascript (Only asked if technical architect of higher position)
Generator functions in JavaScript are a special type of function that can be paused and resumed, allowing you to
control the flow of execution manually. They are defined using the function*
syntax and use the
yield
keyword to produce a sequence of values lazily.
Here is a basic example of a generator function:
javascriptfunction* simpleGenerator() {
yield 1;
yield 2;
yield 3;
}
const generator = simpleGenerator();
console.log(generator.next()); // { value: 1, done: false }
console.log(generator.next()); // { value: 2, done: false }
console.log(generator.next()); // { value: 3, done: false }
console.log(generator.next()); // { value: undefined, done: true }
In this example, the simpleGenerator
function, when invoked, returns a generator object. The
next
method of the generator is used to advance its execution until the next yield
statement
is encountered. The result of each yield
statement is an object with a value
property and a
done
property indicating whether the generator has finished.
Key features of generator functions:
-
Pausing and Resuming:
-
Generator functions can be paused at a
yield
statement, allowing you to control the flow of execution.
-
Generator functions can be paused at a
-
Lazy Execution:
-
Values are produced lazily. The generator only computes the next value when requested through the
next
method.
-
Values are produced lazily. The generator only computes the next value when requested through the
-
Stateful:
-
Generator functions maintain their internal state between calls to
next
, allowing them to remember their position.
-
Generator functions maintain their internal state between calls to
-
Infinite Sequences:
- Generator functions can be used to represent infinite sequences of values because they generate values on demand.
Here's an example of an infinite sequence generator:
javascriptfunction* infiniteSequence() {
let i = 0;
while (true) {
yield i++;
}
}
const generator = infiniteSequence();
console.log(generator.next().value); // 0
console.log(generator.next().value); // 1
console.log(generator.next().value); // 2
// ...
Generators are commonly used in asynchronous programming, such as with the async/await
syntax, to
simplify asynchronous code and make it look more synchronous.
javascriptasync function fetchData() {
const data1 = await fetchData1();
const data2 = await fetchData2();
return [data1, data2];
}
Generator functions provide a more manual approach to achieving similar results. They offer a powerful tool for creating iterators and handling asynchronous code with a more explicit control flow.
43. implement Array.concat, Array.forEach, Array.map, Array.flat using es5
Note that these implementations are simplified and may not cover all edge cases handled by the native Array methods in modern JavaScript.
44. Array.concat:
javascriptfunction concat() {
var result = [];
for (var i = 0; i < arguments.length; i++) {
if (Array.isArray(arguments[i])) {
for (var j = 0; j < arguments[i].length; j++) {
result.push(arguments[i][j]);
}
} else {
result.push(arguments[i]);
}
}
return result;
}
// Example
var arr1 = [1, 2];
var arr2 = [3, 4];
var combined = concat(arr1, arr2, 5, [6]);
console.log(combined); // [1, 2, 3, 4, 5, 6]
45. Array.forEach:
javascriptfunction forEach(arr, callback) {
for (var i = 0; i < arr.length; i++) {
callback(arr[i], i, arr);
}
}
// Example
var numbers = [1, 2, 3];
forEach(numbers, function (value, index) {
console.log(value, index);
});
46. Array.map:
javascriptfunction map(arr, callback) {
var result = [];
for (var i = 0; i < arr.length; i++) {
result.push(callback(arr[i], i, arr));
}
return result;
}
// Example
var numbers = [1, 2, 3];
var squared = map(numbers, function (value) {
return value * value;
});
console.log(squared); // [1, 4, 9]
47. Array.flat:
javascriptfunction flat(arr, depth) {
var result = [];
depth = depth || 1;
function flatten(input, currentDepth) {
for (var i = 0; i < input.length; i++) {
if (Array.isArray(input[i]) && currentDepth < depth) {
flatten(input[i], currentDepth + 1);
} else {
result.push(input[i]);
}
}
}
flatten(arr, 0);
return result;
}
// Example
var nestedArray = [1, [2, [3, 4]]];
var flattenedArray = flat(nestedArray, 2);
console.log(flattenedArray); // [1, 2, [3, 4]]
Please note that these implementations are simplified and may not cover all the edge cases handled by the native Array
methods in modern JavaScript. Also, the Array.flat
implementation is basic and only supports a specified
depth. The native Array.flat
method in modern JavaScript supports flatting to any depth with the use of
Infinity
.
48. Algorithmic question
- Find string is palindrome or not
49. - Find number is a prime number or not
*
e.g.
Sample
50. - Find no of island e.g. Sample
Do it by yourself, for practice
51. - Flatten array without using Array.prototype.flat
Do it by yourself, for practice
52. - Find second-highest number in array of sorted and un sorted array (Optimise way)
Do it by yourself, for practice
53. - Find word with second-highest frequency in a paragraph
Do it by yourself, for practice
54. - Split word with vowels with and without using regular expression
Do it by yourself, for practice
55. - There are some petrol pump in circle. They have Total fuel to just cover round journey by a vehicle.
56. - Find pairs of number from given array whose sum is 10.
58. Local Storage:
-
Capacity:
- Size: Up to 5 MB per domain.
- Scope: Persistent across browser sessions.
-
Lifetime:
- Persistence: Data persists even when the browser is closed and reopened.
-
Scope:
- Global: Data is accessible across browser tabs and windows for the same domain.
-
Use Cases:
- Storing preferences and settings.
- Caching static assets for faster page loading.
- Long-term data storage.
59. Session Storage:
-
Capacity:
- Size: Up to 5 MB per domain.
- Scope: Limited to the duration of the page session.
-
Lifetime:
- Persistence: Data is cleared when the browser session ends (when the browser or tab is closed).
-
Scope:
- Local: Data is accessible only within the same tab or window.
-
Use Cases:
- Storing temporary data needed for a single session.
- Implementing features that require data to be available only while the user is on the page.
61. Other Client-Side Storage Options:
-
IndexedDB:
- A low-level API for storing large amounts of structured data. It offers a more powerful and flexible solution but has a steeper learning curve.
-
Web SQL Database (deprecated):
- A relational database API that is now deprecated and not recommended for use in new projects.
62. When to Use What:
-
Local Storage:
- Use for long-term storage.
- When you need to persist data across browser sessions.
- For preferences and settings.
-
Session Storage:
- Use for short-term storage.
- When data is only needed for the duration of a single page session.
- For temporary data that can be discarded when the user closes the tab or window.
-
Cookies:
- Use when server-side access to data is required.
- For small amounts of data needed for both short-term and long-term use.
- When data needs to be sent to the server with each HTTP request.
-
IndexedDB:
- Use for storing large amounts of structured data.
- When a more powerful, asynchronous storage solution is needed.
It's essential to consider factors such as data size, persistence requirements, and accessibility scope when choosing a client-side storage solution for a specific use case. In many scenarios, developers use a combination of these storage options based on their specific needs.
63. what is JWT tokens. Benefits of using JWT tokens over session. What is best place to store JWT tokens, or secure items.
JWT (JSON Web Token):
JWT, or JSON Web Token, is a compact, URL-safe means of representing claims between two parties. It is often used for authentication and information exchange in web development. JWTs consist of three parts: a header, a payload, and a signature. These parts are encoded and concatenated to form the token.
64. Benefits of Using JWT Tokens Over Session:
-
Stateless:
- JWTs are stateless, meaning the server does not need to store the token's state. This allows for easy horizontal scaling and reduces the need for server-side storage.
-
Compact and Efficient:
- JWTs are compact and can be easily transmitted over the network. This is particularly advantageous in scenarios where bandwidth is a concern.
-
Decentralized Authentication:
- JWTs allow for decentralized authentication, meaning that different services or microservices can issue and verify JWTs independently.
-
Claims and Information:
- JWTs can contain claims (pieces of information) that can be used to convey user roles, permissions, and other details. This reduces the need for additional server-side queries.
-
Standardized Format:
- JWTs follow a standardized format, making them interoperable across different systems and programming languages.
-
Cross-Domain Usage:
- JWTs can be used in cross-domain scenarios, facilitating single sign-on (SSO) between different applications.
65. Best Place to Store JWT Tokens or Secure Items:
-
HTTP Only Cookies:
- Storing JWTs in HTTP-only cookies adds an additional layer of security by preventing client-side JavaScript from accessing the token directly. This helps mitigate certain types of attacks, such as Cross-Site Scripting (XSS).
-
Secure and HttpOnly Flags:
- Ensure that the cookie is marked as "Secure" to only transmit over HTTPS, and use the "HttpOnly" flag to prevent client-side access.
-
Token Expiry and Refresh Tokens:
- Include an expiration time in the JWT payload and implement token refreshing. This helps mitigate the risk of long-lived tokens.
-
Secure Storage Mechanisms:
- If not using cookies, store JWTs securely in a client-side storage mechanism, such as Web Storage (localStorage or sessionStorage). However, be cautious of XSS attacks in this scenario.
-
Use HTTPS:
- Ensure that your application uses HTTPS to encrypt data in transit, preventing eavesdropping and man-in-the-middle attacks.
-
Token Blacklisting:
- Implement token blacklisting to invalidate compromised tokens. This can be done by maintaining a list of revoked or expired tokens on the server.
66. Considerations:
-
Sensitive Information:
- Avoid storing sensitive information in the JWT payload as it is visible to the client.
-
Token Revocation:
- Implement a mechanism for token revocation in case a token needs to be invalidated before its expiration time.
-
Encryption:
- For additional security, consider encrypting JWTs if the information they carry needs to be confidential.
By following best practices for storing and securing JWTs, developers can harness the benefits of this token-based authentication approach while maintaining a high level of security.
67. what will be output of following:
variable hoisting
var x = 5;
console.log(x);
function a() {
console.log(x);
var x = 6;
console.log(x);
return x;
}
console.log(x)
console.log(a())
do by yourself
68. concept of use strict
'use strict';
var x = 5;
console.log(x);
function a() {
console.log(x);
var x = 6;
console.log(x);
return x;
}
console.log(x)
console.log(a())
69. Concept of this
console.log(this);
[5].forEach((i) => {
console.log(this.length);
})
[5].forEach(function (i) {
console.log(this.length);
})
var a = {
x1: () => {
console.log(this);
},
x2: function () {
console.log(this);
}
}
a.x1();
var temp = () => {
this.x1();
}
temp();
temp.apply(a, [])
var temp1 = () => {
this.x1();
}
temp1 = temp1.bind(a);
temp1()
70. what is lexical scope/environment
Lexical scope, also known as static scope, is a concept in programming languages, including JavaScript, that describes how the scope of variables is determined at the time of lexical (static) analysis, i.e., during the creation of the code, rather than at runtime. Lexical scope is defined by the physical structure of the code and the placement of variables and blocks within the code.
In lexical scope:
-
Scope Hierarchy:
- Variables are defined within blocks, functions, or the global scope.
- The scope of a variable is determined by its location in the source code.
-
Access to Variables:
- Inner blocks or functions can access variables defined in their containing (outer) blocks or functions.
- Variables are accessible both upward and downward in the scope chain.
Here's an example in JavaScript:
javascriptfunction outer() {
const outerVar = 'I am from outer';
function inner() {
const innerVar = 'I am from inner';
console.log(outerVar); // Accessing outerVar from the outer scope
console.log(innerVar); // Accessing innerVar from the same scope
}
inner();
}
outer();
In this example, inner
has access to both outerVar
and innerVar
. The scope of
outerVar
extends to the inner function because of lexical scoping.
71. Lexical Environment:
The lexical environment is a structure that holds identifier-variable mapping, and it is created during the lexical phase of code execution. It consists of two components:
-
Environment Record:
- A data structure that maps identifier names to variable values.
-
Reference to the Outer Environment:
- A reference to the lexical environment of the containing (outer) scope.
The lexical environment helps determine the value of a variable when it's accessed in the code.
javascriptfunction outer() {
const outerVar = 'I am from outer';
function inner() {
const innerVar = 'I am from inner';
console.log(outerVar);
}
inner();
}
outer();
In this example, the lexical environment of inner
includes an environment record with mappings for
innerVar
and a reference to the lexical environment of outer
. This reference allows
inner
to access variables from the outer scope, creating a chain of lexical environments.
In summary, lexical scope is a fundamental concept that influences how variables are accessed and resolved in a programming language. It is based on the physical structure of the code and determines the scope of variables at compile time. Lexical scope is used in many modern programming languages to provide clear rules for variable resolution and scoping.
72. What are polyfills.
Polyfills are code snippets or scripts that provide modern functionality to older browsers that lack support for certain features or APIs. The term "polyfill" is a combination of "poly," meaning many, and "fill," implying the filling of gaps or adding missing functionality. Polyfills are often used to bridge the compatibility gap between older browsers and the latest web standards.
Here's how polyfills work and why they are important:
73. How Polyfills Work:
-
Feature Detection:
- Polyfills often start by checking if a particular feature or API is supported in the user's browser.
- Modern web development practices typically involve feature detection to determine whether a browser supports a specific functionality.
-
Conditional Loading:
- If the feature is not supported, the polyfill script is loaded conditionally, injecting the missing functionality into the browser.
- If the feature is supported, the polyfill may not be loaded, reducing unnecessary overhead.
-
Providing Missing Functionality:
- The polyfill script contains JavaScript code that emulates the desired functionality or implements missing APIs using standard web technologies.
-
Enhancing Cross-Browser Compatibility:
- Polyfills enhance cross-browser compatibility by enabling developers to use the latest web features while ensuring that their applications still function on older browsers.
74. Why Polyfills are Important:
-
Support for New Web Standards:
- Browsers evolve, and new web standards are introduced. Polyfills allow developers to use these standards without worrying about lack of support in older browsers.
-
Progressive Enhancement:
- Developers can build applications with the latest features and progressively enhance them with polyfills to ensure a consistent experience across various browsers.
-
Reduced Fragmentation:
- Polyfills help reduce browser fragmentation by enabling developers to write code that works uniformly across different browsers, regardless of their version.
-
Maintainability:
- Using polyfills can simplify code maintenance by allowing developers to adopt new features without writing complex browser-specific code.
75. what is v8 engine
The V8 engine is an open-source JavaScript engine developed by Google. It is primarily used in the Google Chrome web browser but is also employed in various other projects and applications, including Node.js. V8 is designed to execute JavaScript code and provides a high-performance runtime environment.
76. V8 Engine Architecture:
The architecture of the V8 engine consists of several components that work together to parse, compile, optimize, and execute JavaScript code efficiently. Here are the key components of the V8 engine architecture:
-
Parser:
- The parser reads and interprets the JavaScript source code, converting it into an Abstract Syntax Tree (AST).
-
Ignition Interpreter:
- The Ignition interpreter is a lightweight JavaScript interpreter. It quickly translates the AST into bytecode, a lower-level representation of the code.
-
TurboFan Compiler:
- The TurboFan compiler is responsible for generating highly optimized machine code from the bytecode produced by the Ignition interpreter.
- TurboFan performs various optimization techniques, including inlining functions, loop unrolling, and type specialization, to produce efficient machine code.
-
Garbage Collector:
- V8 includes a garbage collector to manage memory. The garbage collector automatically identifies and reclaims memory that is no longer in use, helping to prevent memory leaks.
-
Profiler:
- The profiler collects runtime information about the execution of JavaScript code. This information is used to identify hot functions and improve optimization decisions.
-
Heap and Stack:
- The memory in V8 is organized into a heap and a stack. The heap stores objects dynamically allocated during program execution, while the stack is used for function calls and local variables.
-
Execution Pipeline:
- The overall execution pipeline involves parsing the JavaScript source code, generating bytecode, interpreting bytecode with Ignition, and optimizing critical parts of the code with TurboFan.
77. Execution Flow:
-
Parsing:
- The JavaScript source code is parsed into an Abstract Syntax Tree (AST).
-
Ignition (Interpreter):
- The Ignition interpreter quickly translates the AST into bytecode.
-
Execution:
- The bytecode is executed by the Ignition interpreter for quick start-up performance.
-
Profiling:
- Profiling information is collected during execution.
-
Optimization:
- The TurboFan compiler uses profiling information to generate highly optimized machine code.
-
Garbage Collection:
- The garbage collector manages memory, reclaiming unused memory to prevent leaks.
78. Characteristics:
-
Just-In-Time (JIT) Compilation:
- V8 uses a combination of interpreting and just-in-time (JIT) compilation to execute JavaScript code efficiently.
-
Optimization Techniques:
- TurboFan employs advanced optimization techniques to generate highly optimized machine code, adapting to the runtime characteristics of the code.
-
Concurrency:
- V8 is designed to execute JavaScript code concurrently, leveraging multiple CPU cores for improved performance.
Understanding the architecture of the V8 engine is crucial for developers working with JavaScript, especially when optimizing code for better performance in web applications or server-side environments using Node.js.
79. what all javascript engines are their in market and which all browsers use them.
Several JavaScript engines are used by different web browsers to interpret and execute JavaScript code. Here are some prominent JavaScript engines and the browsers that use them:
-
V8 (Google Chrome, Node.js):
- Browsers: Google Chrome, Chromium-based browsers (e.g., Microsoft Edge, Opera, Brave).
- Usage: V8 is also used as the runtime engine for Node.js.
-
SpiderMonkey (Mozilla Firefox):
- Browsers: Mozilla Firefox.
- Usage: SpiderMonkey is the JavaScript engine developed by Mozilla.
-
JavaScriptCore (WebKit, Safari):
- Browsers: Apple Safari, some versions of Google Chrome (before the switch to V8).
- Usage: JavaScriptCore is the engine used by the WebKit rendering engine, which powers Safari.
-
Chakra (Microsoft Edge, Internet Explorer):
- Browsers: Microsoft Edge (legacy versions), Internet Explorer.
- Note: Microsoft Edge has transitioned to using the Blink rendering engine and V8 JavaScript engine, making Chakra obsolete in newer versions of Edge.
-
Nitro (Safari on iOS):
- Browsers: Safari on iOS devices.
- Usage: Nitro is an optimized version of the JavaScriptCore engine tailored for iOS.
-
Rhino (Mozilla Rhino):
- Usage: Rhino is a JavaScript engine for Java applications. It is not commonly used in web browsers but may be utilized in Java-based environments.
-
JerryScript:
- Usage: JerryScript is a lightweight JavaScript engine designed for resource-constrained devices and the Internet of Things (IoT).
-
Duktape:
- Usage: Duktape is an embeddable JavaScript engine that can be integrated into various applications and platforms.
It's worth noting that some browsers, especially those based on the Blink rendering engine (like Chrome and new versions of Microsoft Edge), use the V8 JavaScript engine. Additionally, the choice of JavaScript engine can impact the performance of web applications, so browser developers often focus on optimizing and improving their respective engines.