What is the difference between let and var?
What is the difference between null and undefined?
What is the difference between __proto__ and prototype?
What is the difference between Call, Apply and Bind?
What is JSON and its common operations?
What are lambda expressions or arrow functions?
What is a first class function?
What is a first order function?
What is a higher order function?
What is the currying function?
How do you redeclare variables in a switch block without an error?
What is the Temporal Dead Zone?
What is an IIFE (Immediately Invoked Function Expression)?
What is the purpose of double exclamation?
What are the differences between undeclared and undefined variables?
What is the difference between document load and DOMContentLoaded events?
What is the difference between native, host and user objects?
What is the purpose of void 0?
What is the use of preventDefault() method?
What is the use of stopPropagation() method?
How do you assign default values to variables?
How do you define multiline strings?
What would be the result of 1+2+'3'?
Can you apply chaining on conditional operator?
Can you give an example of when you really need a semicolon?
How do you detect JavaScript disabled in the page?
What is the purpose of seal() method?
What are the differences between freeze() and seal() methods?
How do you get enumerable key and value pairs?
What is the main difference between Object.values() and Object.entries() method?
How can you get the list of keys of any object?
How do you create an object with prototype?
What is an anonymous function?
What are JavaScript accessors?
What is Obfuscation in JavaScript?
Does JavaScript supports namespace?
Why do we call JavaScript as Dynamic Language?
What is the output of the following for loops?
List down some of the features of ES6?
What is the difference between let and var?
- var
- let
Let's take an example to see the difference:
function userDetails(username) { if (username) { console.log(salary); // undefined due to hoisting console.log(age); // ReferenceError: Cannot access 'age' before initialization let age = 30; var salary = 10000; } console.log(salary); // 10000 (accessible due to function scope) console.log(age); // error: age is not defined (due to block scope) } userDetails("John");
What is the difference between null and undefined?
- null
- undefined
What is a prototype chain?
The prototype chain in JavaScript is a mechanism that allows objects to inherit properties and methods from other objects.
function Person(name) { this.name = name; } Person.prototype.sayHello = function () { console.log(`Hello, my name is ${this.name}`); }; const user = new Person("Orkhan"); user.sayHello(); // "Hello, my name is Orkhan" console.log(user.__proto__ === Person.prototype); // true console.log(Person.prototype.__proto__ === Object.prototype); // true console.log(Object.prototype.__proto__ === null); // true (end of chain)
What is the difference between __proto__ and prototype?
The difference between __proto__ and prototype in JavaScript is crucial to understanding how inheritance works.
- prototype
- __proto__
prototype is a blueprint for creating objects (applies to constructor functions and classes).
__proto__ links objects to their prototype, enabling inheritance.
What is the difference between Call, Apply and Bind?
- call()
The call() method invokes a function with a given this value and arguments provided one by one:
let employee1 = { firstName: "John", lastName: "Rodson" }; let employee2 = { firstName: "Jimmy", lastName: "Baily" }; function invite(greeting1, greeting2) { console.log(`${greeting1} ${this.firstName} ${this.lastName}, ${greeting2}`); } invite.call(employee1, "Hello", "How are you?"); // Hello John Rodson, How are you? invite.call(employee2, "Hello", "How are you?"); // Hello Jimmy Baily, How are you?
- apply()
Invokes the function with a given this value and allows you to pass in arguments as an array:
let employee1 = { firstName: "John", lastName: "Rodson" }; let employee2 = { firstName: "Jimmy", lastName: "Baily" }; function invite(greeting1, greeting2) { console.log(`${greeting1} ${this.firstName} ${this.lastName}, ${greeting2}`); } invite.apply(employee1, ["Hello", "How are you?"]); // Hello John Rodson, How are you? invite.apply(employee2, ["Hello", "How are you?"]); // Hello Jimmy Baily, How are you?
- bind()
Returns a new function, allowing you to pass any number of arguments:
let employee1 = { firstName: "John", lastName: "Rodson" }; let employee2 = { firstName: "Jimmy", lastName: "Baily" }; function invite(greeting1, greeting2) { console.log(`${greeting1} ${this.firstName} ${this.lastName}, ${greeting2}`); } let inviteEmployee1 = invite.bind(employee1); let inviteEmployee2 = invite.bind(employee2); inviteEmployee1("Hello", "How are you?"); // Hello John Rodson, How are you? inviteEmployee2("Hello", "How are you?"); // Hello Jimmy Baily, How are you?
Call and Apply are pretty much interchangeable. Both execute the current function immediately. You need to decide whether it’s easier to send in an array or a comma separated list of arguments. You can remember by treating Call is for comma (separated list) and Apply is for Array.
Bind creates a new function that will have this set to the first parameter passed to bind().
What is JSON and its common operations?
JSON is a text-based data format following JavaScript object syntax, which was popularized by Douglas Crockford. It is useful when you want to transmit data across a network. It is basically just a text file with an extension of .json, and a MIME type of application/json.
- Parsing: Converting a string to a native object:
JSON.parse(text);
- Stringification: Converting a native object to a string so that it can be transmitted across the network:
JSON.stringify(object);
let myObj = { name: "Orkhan", surname: "Alishov" }; console.log(myObj); // {name: 'Orkhan', surname: 'Alishov'} let stringifyObj = JSON.stringify(myObj); console.log(stringifyObj); // {"name":"Orkhan","surname":"Alishov"} let parseObj = JSON.parse(stringifyObj); console.log(parseObj); // {name: 'Orkhan', surname: 'Alishov'}
What are lambda expressions or arrow functions?
An arrow function is a shorter/concise syntax for a function expression and does not have its own this, arguments, super, or new.target. These functions are best suited for non-method functions, and they cannot be used as constructors.
Some of the examples of arrow functions are listed as below:
const arrowFunc1 = (a, b) => a + b; // Multiple parameters const arrowFunc2 = a => a * 10; // Single parameter const arrowFunc3 = () => {} // no parameters
In JavaScript, arrow functions (also known as lambda expressions) are a shorter syntax for writing functions. They were introduced in ES6 (ECMAScript 2015) and provide a more concise way to write function expressions.
- Implicit Return
If the function body has only one expression, {} and return can be omitted:
const multiply = (a, b) => a * b; console.log(multiply(3, 4)); // 12
- Single Parameter Does Not Need Parentheses
When there's only one parameter, you can omit ():
const greet = name => `Hello, ${name}!`; console.log(greet("Orkhan")); // "Hello, Orkhan!"
- No Own this Binding
Arrow functions do not bind their own this. Instead, they inherit this from the surrounding function:
const person = { name: "Orkhan", greet: function () { setTimeout(() => { console.log(`Hello, my name is ${this.name}`); }, 1000); }, test: function () { console.log(this.name); }, test2: () => { console.log(this.name); } }; person.greet(); // "Hello, my name is Orkhan" person.test(); // Orkhan person.test2(); //
- Cannot Be Used as a Constructor
Arrow functions cannot be used with new:
const Person = (name) => { this.name = name; // This will not work }; const user = new Person("Orkhan"); // TypeError: Person is not a constructor
- No arguments Object
function traditionalFunction() { console.log(arguments); // Works } const arrowFunction = () => { console.log(arguments); // ReferenceError }; traditionalFunction(1, 2, 3); arrowFunction(1, 2, 3);
What is a first class function?
A first-class function means that functions in JavaScript are treated as first-class citizens. This means functions can be:
// Assigning a Function to a Variable const greet = function(name) { return `Hello, ${name}!`; }; console.log(greet("Orkhan")); // "Hello, Orkhan!" // Passing a Function as an Argument // Functions can be passed as arguments to other functions (also called callback functions) function operate(a, b, operation) { return operation(a, b); } const add = (x, y) => x + y; const multiply = (x, y) => x * y; console.log(operate(5, 3, add)); // 8 console.log(operate(5, 3, multiply)); // 15 // Returning a Function from Another Function function createGreeting(greeting) { return function(name) { return `${greeting}, ${name}!`; }; } const sayHello = createGreeting("Hello"); console.log(sayHello("Orkhan")); // "Hello, Orkhan!" // Storing Functions in Data Structures const operations = { add: (a, b) => a + b, subtract: (a, b) => a - b, }; console.log(operations.add(5, 2)); // 7 console.log(operations.subtract(5, 2)); // 3
What is a first order function?
A first-order function is a function that does not take another function as an argument and does not return a function. It operates only on values (numbers, strings, objects, etc.) rather than on other functions.
function square(num) { return num * num; } console.log(square(5)); // 25
square is a first-order function because it takes a number (num) and returns a number. It does not take or return another function.
What is a higher order function?
A higher-order function is a function that accepts another function as an argument or returns a function as a return value or both. The syntactic structure of higher order function will be as follows:
const firstOrderFunc = () => console.log("Hello, I am a First order function"); const higherOrder = (ReturnFirstOrderFunc) => ReturnFirstOrderFunc(); higherOrder(firstOrderFunc); // Hello, I am a First order function
You can also call the function which you are passing to higher order function as callback function.
The higher order function is helpful to write the modular and reusable code.
- Built-in Higher-Order Functions in JavaScript
JavaScript provides several built-in HOFs:
map() – Transforms Each Element in an Array;
filter() – Filters Elements Based on a Condition;
reduce() – Accumulates a Single Value;
What is a unary function?
A unary function (i.e. monadic) is a function that accepts exactly one argument. It stands for a single argument accepted by a function.
Let us take an example of unary function:
const unaryFunction = (a) => console.log(a + 10); unaryFunction(5); // 15
What is the currying function?
Currying is the process of taking a function with multiple arguments and turning it into a sequence of functions each with only a single argument. Currying is named after a mathematician Haskell Curry. By applying currying, an n-ary function turns into a unary function.
Let's take an example of n-ary function and how it turns into a currying function:
const multiArgFunction = (a, b, c) => a + b + c; console.log(multiArgFunction(1, 2, 3)); // 6 const curryUnaryFunction = (a) => (b) => (c) => a + b + c; curryUnaryFunction(1); // returns a function: b => c => 1 + b + c curryUnaryFunction(1)(2); // returns a function: c => 3 + c curryUnaryFunction(1)(2)(3); // returns the number 6
Curried functions are great to improve code reusability and functional composition.
What is a pure function?
A Pure function is a function where the return value is only determined by its arguments without any side effects. i.e, If you call a function with the same arguments 'n' number of times and 'n' number of places in the application then it will always return the same value.
Let's take an example to see the difference between pure and impure functions:
let numberArray = []; // Impure const impureAddNumber = (number) => numberArray.push(number); // Pure const pureAddNumber = (number) => (argNumberArray) => argNumberArray.concat([number]); // Display the results console.log(impureAddNumber(6)); // 1 console.log(numberArray); // [6] console.log(pureAddNumber(7)(numberArray)); // [6, 7] console.log(numberArray); // [6]
As per the above code snippets, the Push function is impure itself by altering the array and returning a push number index independent of the parameter value, whereas Concat on the other hand takes the array and concatenates it with the other array producing a whole new array without side effects. Also, the return value is a concatenation of the previous array.
Remember that Pure functions are important as they simplify unit testing without any side effects and no need for dependency injection. They also avoid tight coupling and make it harder to break your application by not having any side effects. These principles are coming together with the Immutability concept of ES6: giving preference to const over let usage.
How do you redeclare variables in a switch block without an error?
If you try to redeclare variables in a switch block then it will cause errors because there is only one block. For example, the below code block throws a syntax error as below:
let counter = 1; switch (x) { case 0: let name; break; case 1: let name; // Uncaught SyntaxError: Identifier 'name' has already been declared break; }
To avoid this error, you can create a nested block inside a case clause and create a new block scoped lexical environment:
let counter = 1; switch (x) { case 0: { let name; break; } case 1: { let name; // No SyntaxError for redeclaration break; } }
What is the Temporal Dead Zone?
The Temporal Dead Zone (TDZ) is a specific period or area of a block where a variable is inaccessible until it has been initialized with a value. This behavior in JavaScript that occurs when declaring a variable with the let and const keywords, but not with var. In ECMAScript 6, accessing a let or const variable before its declaration (within its scope) causes a ReferenceError.
Let's see this behavior with an example:
function something() { console.log(counter1); // undefined console.log(counter2); // Uncaught ReferenceError: Cannot access 'counter2' before initialization var counter1 = 1; let counter2 = 2; } something();
What is an IIFE (Immediately Invoked Function Expression)?
IIFE (Immediately Invoked Function Expression) is a JavaScript function that runs as soon as it is defined. The signature of it would be as below:
(function () { // logic here })();
The primary reason to use an IIFE is to obtain data privacy because any variables declared within the IIFE cannot be accessed by the outside world. i.e, If you try to access variables from the IIFE then it throws an error as below:
(function () { var message = "IIFE"; console.log(message); // IIFE })(); console.log(message); // Uncaught ReferenceError: message is not defined
What is Memoization?
Memoization is a functional programming technique which attempts to increase a function’s performance by caching its previously computed results. Each time a memoized function is called, its parameters are used to index the cache. If the data is present, then it can be returned, without executing the entire function. Otherwise the function is executed and then the result is added to the cache. Let's take an example of adding function with memoization:
const memoizeAddition = () => { let cache = {}; return (value) => { if (value in cache) { console.log("Fetching from cache"); return cache[value]; } else { console.log("Calculating result"); let result = value + 20; cache[value] = result; return result; } }; }; // Returned function from memoizeAddition const addition = memoizeAddition(); console.log(addition(20)); // Calculating result: 40 console.log(addition(20)); // Fetching from cache: 40
What is Hoisting?
Hoisting is a JavaScript mechanism where variables, function declarations and classes are moved to the top of their scope before code execution. Remember that JavaScript only hoists declarations, not initialisation. Let's take a simple example of variable hoisting:
console.log(message); // undefined var message = "The variable has been hoisted";
The above code looks like as below to the interpreter:
var message; console.log(message); message = "The variable has been hoisted";
In the same fashion, function declarations are hoisted too:
message("Good morning"); // Good morning function message(name) { console.log(name); }
This hoisting makes functions to be safely used in code before they are declared.
What are classes in ES6?
In ES6, Javascript classes are primarily syntactic sugar over JavaScript’s existing prototype-based inheritance. For example, the prototype based inheritance written in function expression as below:
function Bike(model, color) { this.model = model; this.color = color; } Bike.prototype.getDetails = function () { return `${this.model} bike has ${this.color} color`; }; let myBike = new Bike('Isma', 'Red'); console.log(myBike.getDetails()); // Isma bike has Red color
Whereas ES6 classes can be defined as an alternative:
class Bike { constructor(color, model) { this.color = color; this.model = model; } getDetails() { return `${this.model} bike has ${this.color} color`; } } let myBike = new Bike('Isma', 'Red'); console.log(myBike.getDetails()); // Isma bike has Red color
What are Closures?
A closure is the combination of a function bundled (enclosed) together with its lexical environment within which that function was declared. i.e, It is an inner function that has access to the outer or enclosing function’s variables, functions and other data even after the outer function has finished its execution. The closure has three scope chains:
Let's take an example of closure concept:
function Welcome(name) { let greetingInfo = function (message) { console.log(`${message} ${name}`); }; return greetingInfo; } let myFunction = Welcome("John"); myFunction("Welcome"); // Welcome John myFunction("Hello Mr."); // Hello Mr. John
As per the above code, the inner function (i.e, greetingInfo) has access to the variables in the outer function scope (i.e, Welcome) even after the outer function has returned.
What is a Promise?
A Promise in JavaScript is an object that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Promises are a key part of handling asynchronous behavior in modern JavaScript, replacing older patterns like callback functions. It will be in one of the 3 possible states: fulfilled, rejected, or pending.
Once a Promise transitions to either fulfilled or rejected, it cannot change its state again.
Promises allow chaining using .then() and .catch() methods, making it easier to work with sequences of asynchronous operations.
The syntax of Promise creation looks like below:
const promise = new Promise((resolve, reject) => { // Perform some asynchronous operation let success = true; // Simulated condition if (success) { resolve("Operation succeeded!"); // Fulfill the promise } else { reject("Operation failed!"); // Reject the promise } }); promise .then((result) => { console.log(result); // Logs: "Operation succeeded!" }) .catch((error) => { console.error(error); // Logs: "Operation failed!" (if rejected) }) .finally(() => { console.log("Promise is done!"); // Always runs });
- Handling Promises:
Promises are used to handle asynchronous operations. They provide an alternative approach for callbacks by reducing the callback hell and writing the cleaner code.
What is a Callback function?
A callback function is a function passed into another function as an argument. This function is invoked inside the outer function to complete an action. Let's take a simple example of how to use callback function:
function callbackFunction(name) { console.log(`Hello, ${name}`); } function outerFunction(callback) { let name = prompt("Please enter your name."); callback(name); } outerFunction(callbackFunction);
Why do we need Callbacks?
The callbacks are needed because JavaScript is an event driven language. That means instead of waiting for a response, JavaScript will keep executing while listening for other events. Let's take an example with the first function invoking an API call (simulated by setTimeout) and the next function which logs the message.
function firstFunction() { // Simulate a code delay setTimeout(function () { console.log("First function called"); }, 1000); } function secondFunction() { console.log("Second function called"); } firstFunction(); secondFunction(); // Second function called // First function called
As observed from the output, JavaScript didn't wait for the response of the first function and the remaining code block got executed. So callbacks are used in a way to make sure that certain code doesn’t execute until the other code finishes execution.
What is a Callback Hell?
Callback Hell is an anti-pattern with multiple nested callbacks which makes code hard to read and debug when dealing with asynchronous logic. The callback hell looks like below:
async1(function() { async2(function() { async3(function() { async4(function() { ... }); }); }); });
What is Promise Chaining?
The process of executing a sequence of asynchronous tasks one after another using promises is known as Promise chaining. Let's take an example of promise chaining for calculating the final result:
new Promise(function (resolve, reject) { setTimeout(() => resolve(1), 1000); }) .then(function (result) { console.log(result); // 1 return result * 2; }) .then(function (result) { console.log(result); // 2 return result * 3; }) .then(function (result) { console.log(result); // 6 return result * 4; });
In the above handlers, the result is passed to the chain of .then() handlers with the below work flow:
What is the purpose of double exclamation?
The double exclamation mark (!!) in JavaScript is used to convert a value to a boolean. It is a shorthand way of coercing a value into its boolean equivalent.
Here's how it works:
It is typically used to ensure a value is either true or false explicitly, rather than relying on truthy or falsy values.
const value = "hello"; console.log(!!value); // true (since "hello" is truthy) const emptyString = ""; console.log(!!emptyString); // false (since "" is falsy) const number = 0; console.log(!!number); // false (since 0 is falsy) const undefinedValue = undefined; console.log(!!undefinedValue); // false (since undefined is falsy)
When to use:
This is just syntactic sugar, as JavaScript will naturally treat truthy and falsy values as booleans in conditional statements. However, !! makes the intention explicit.
What is eval?
The eval() function in JavaScript is a global function that evaluates a string as JavaScript code. Essentially, it takes a string argument, interprets it as code, and executes it.
const x = 10; const y = 20; const result = eval("x + y"); // Evaluates as 10 + 20 console.log(result); // 30
While eval() can be useful in some rare cases (like dynamic code execution), its use is generally discouraged because:
Alternatives to eval():
Use JSON.parse() for parsing JSON strings instead of eval.
Use dynamic function constructors like Function if necessary, but with caution:
const func = new Function("x", "y", "return x + y;"); console.log(func(10, 20)); // 30
In most modern applications, eval() should be avoided unless there is a very strong justification.
What are the differences between undeclared and undefined variables?
- undeclared
- undefined
Always declare variables with let or const to avoid issues with undeclared variables.
Use tools like linters (e.g., ESLint) to detect undeclared variables and enforce best practices.
What is the difference between document load and DOMContentLoaded events?
The DOMContentLoaded event is fired when the initial HTML document has been completely loaded and parsed, without waiting for assets (stylesheets, images, and subframes) to finish loading.
Whereas the load event is fired when the whole page has loaded, including all dependent resources (stylesheets, images).
What is the difference between native, host and user objects?
Native objects are objects that are part of the JavaScript language defined by the ECMAScript specification. For example, String, Math, RegExp, Object, Function etc. core objects defined in the ECMAScript spec.
Host objects are objects provided by the browser or runtime environment (Node). For example, window, XmlHttpRequest, DOM nodes etc. are considered as host objects.
User objects are objects defined in the JavaScript code. For example, User objects created for profile information.
What is the purpose of void 0?
void(0) is used to prevent the page from refreshing.
This will be helpful to eliminate the unwanted side-effect, because it will return the undefined primitive value. It is commonly used for HTML documents that use href="JavaScript:Void(0);" within an <a> element. i.e, when you click a link, the browser loads a new page or refreshes the same page. But this behavior will be prevented using this expression. For example, the below link notify the message without reloading the page:
<a href="JavaScript:void(0);" onclick="alert('Well done!')"> Click Me! </a>
What is the use of preventDefault() method?
The preventDefault() method cancels the event if it is cancelable, meaning that the default action or behaviour that belongs to the event will not occur.
For example, prevent form submission when clicking on submit button and prevent opening the page URL when clicking on hyperlink are some common use cases.
document .getElementById("link") .addEventListener("click", function (event) { event.preventDefault(); });
Remember that not all events are cancelable.
What is the use of stopPropagation() method?
The stopPropagation method is used to stop the event from bubbling up the event chain.
For example, the below nested divs with stopPropagation method prevents default event propagation when clicking on nested div (Div1):
<p>Click DIV1 Element</p> <div onclick="secondFunc()"> DIV 2 <div onclick="firstFunc(event)"> DIV 1 </div> </div> function firstFunc(event) { alert("DIV 1"); event.stopPropagation(); } function secondFunc() { alert("DIV 2"); }
What is an arguments object?
The arguments object is an Array-like object accessible inside functions that contains the values of the arguments passed to that function.
For example, let's see how to use arguments object inside sum function:
function sum() { let total = 0; for (let i = 0, len = arguments.length; i < len; ++i) { total += arguments[i]; } return total; } console.log(sum(1, 2, 3)); // 6
How do you assign default values to variables?
You can use the logical or operator || in an assignment expression to provide a default value. The syntax looks like as below:
let a = b || c;
As per the above expression, variable 'a' will get the value of 'c' only if 'b' is falsy (if is null, false, undefined, 0, empty string, or NaN), otherwise 'a' will get the value of 'b'.
How do you define multiline strings?
You can define multiline string literals using the '\n' character followed by line terminator('').
let str = "This is a \n\ very lengthy \n\ sentence!"; console.log(str); /* This is a very lengthy sentence! */ let str2 = "Hi! \ I \ love \ JS!"; console.log(str2); // Hi! I love JS!
But if you have a space after the '\n' character, there will be indentation inconsistencies.
What would be the result of 1+2+'3'?
The output is going to be 33.
Since 1 and 2 are numeric values, the result of the first two digits is going to be a numeric value 3.
The next digit is a string type value because of that the addition of numeric value 3 and string type value 3 is just going to be a concatenation value 33.
Can you apply chaining on conditional operator?
Yes, you can apply chaining on conditional operators similar to if...else if...else if...else chain.
The syntax is going to be as below:
function traceValue(someParam) { return condition1 ? value1 : condition2 ? value2 : condition3 ? value3 : value4; } // The above conditional operator is equivalent to function traceValue(someParam) { if (condition1) { return value1; } else if (condition2) { return value2; } else if (condition3) { return value3; } else { return value4; } }
Can you give an example of when you really need a semicolon?
It is recommended to use semicolons after every statement in JavaScript.
For example, in the below case it throws an error "... is not a function" at runtime due to missing semicolon:
// define a function let fn = (function () { //... })( // semicolon missing at this line // then execute some code inside a closure function () { //... } )();
and it will be interpreted as:
let fn = (function () { //... })(function () { //... })();
In this case, we are passing the second function as an argument to the first function and then trying to call the result of the first function call as a function. Hence, the second function will fail with a "... is not a function" error at runtime.
What is a freeze() method?
The freeze() method is used to freeze an object. Freezing an object does not allow adding new properties to an object, prevents removing, and prevents changing the enumerability, configurability, or writability of existing properties. i.e. It returns the passed object and does not create a frozen copy.
const obj = { prop: 100, }; Object.freeze(obj); obj.prop = 200; // Throws an error in strict mode console.log(obj.prop); // 100
Remember freezing is only applied to the top-level properties in objects but not for nested objects. For example, let's try to freeze user object which has employment details as nested object and observe that details have been changed.
const user = { name: "John", employment: { department: "IT", }, }; Object.freeze(user); user.name = "Orkhan"; user.employment.department = "HR"; console.log(user.name); // John console.log(user.employment.department); // HR
Note: It causes a TypeError if the argument passed is not an object.
Below are the main benefits of using freeze method:
How do you detect JavaScript disabled in the page?
You can use the <noscript> tag to detect JavaScript disabled or not. The code block inside <noscript> gets executed when JavaScript is disabled, and is typically used to display alternative content when the page generated in JavaScript.
<script type="javascript"> // JS related code goes here </script> <noscript> JavaScript is disabled in the page! </noscript>
What is a Rest parameter?
Rest parameter is an improved way to handle function parameters which allows us to represent an indefinite number of arguments as an array. The syntax would be as below:
function f(a, b, ...theArgs) { // ... }
For example, let's take a sum example to calculate on dynamic number of parameters:
function sum(...args) { let total = 0; for (const i of args) { total += i; } return total; } console.log(sum(1, 2)); // 3 console.log(sum(1, 2, 3)); // 6 console.log(sum(1, 2, 3, 4)); // 10 console.log(sum(1, 2, 3, 4, 5)); // 15
Rest parameter is added in ES2015 or ES6.
- What happens if you do not use rest parameter as a last argument?
The rest parameter should be the last argument, as its job is to collect all the remaining arguments into an array. For example, if you define a function like below it doesn’t make any sense and will throw an error.
function someFunc(a, ...b, c) { // Your code goes here return; } // SyntaxError: Rest parameter must be last formal parameter
What is a Spread operator?
Spread operator allows iterables (arrays/objects/strings) to be expanded into single arguments/elements. Let's take an example to see this behavior:
function calculateSum(x, y, z) { return x + y + z; } const numbers = [1, 2, 3]; console.log(calculateSum(...numbers)); // 6
What is the purpose of seal() method?
The Object.seal() method is used to seal an object, by preventing new properties from being added to it and marking all existing properties as non-configurable. But values of present properties can still be changed as long as they are writable. Let's see the below example to understand more about seal() method:
const object = { property: "Welcome to the JS world!", }; Object.seal(object); object.property = "Welcome to the PHP world!"; console.log(Object.isSealed(object)); // true delete object.property; // You cannot delete when sealed console.log(object.property); // Welcome to the PHP world! object.testKey = "Test value"; console.log(object.testKey); // undefined
- Below are the main applications of Object.seal() method:
What are the differences between freeze() and seal() methods?
If an object is frozen using the Object.freeze() method then its properties become immutable and no changes can be made in them whereas if an object is sealed using the Object.seal() method then the changes can be made in the existing properties of the object.
How do you get enumerable key and value pairs?
The Object.entries() method is used to return an array of a given object's own enumerable string-keyed property [key, value] pairs, in the same order as that provided by a for...in loop. Let's see the functionality of object.entries() method in an example:
const object = { a: "Good morning", b: 100, }; for (let [key, value] of Object.entries(object)) { console.log(`${key}: ${value}`); // a: 'Good morning' // b: 100 } console.log(Object.entries(object)); /* (2) [Array(2), Array(2)] 0 : (2) ['a', 'Good morning'] 1 : (2) ['b', 100] */
Note: The order is not guaranteed as object defined.
What is the main difference between Object.values() and Object.entries() method?
The Object.values() method's behavior is similar to Object.entries() method but it returns an array of values instead [key, value] pairs.
const object = { a: "Good morning", b: 100, }; for (let value of Object.values(object)) { console.log(`${value}`); // Good morning // 100 } console.log(Object.values(object)); /* (2) ['Good morning', 100] 0: "Good morning" 1: 100 */
How can you get the list of keys of any object?
You can use the Object.keys() method which is used to return an array of a given object's own property names, in the same order as we get with a normal loop. For example, you can get the keys of a user object:
const user = { name: "John", gender: "male", age: 40, }; console.log(Object.keys(user)); // (3) ['name', 'gender', 'age']
How do you create an object with prototype?
The Object.create() method is used to create a new object with the specified prototype object and properties. i.e, It uses an existing object as the prototype of the newly created object. It returns a new object with the specified prototype object and properties:
const user = { name: "John", printInfo: function() { console.log(`My name is ${this.name}.`); }, }; const admin = Object.create(user); admin.name = "Nick"; // Remember that "name" is a property set on "admin" but not on "user" object admin.printInfo(); // My name is Nick
What is a WeakSet?
WeakSet is used to store a collection of weakly (weak references) held objects. The syntax would be as follows:
new WeakSet([iterable]);
Let's see the below example to explain it's behavior:
let ws = new WeakSet(); let user = {}; console.log(ws); // WeakSet {} ws.add(user); console.log( ws.has(user) ); // true ws.delete(user); // removes user from the set console.log( ws.has(user) ); // false, user has been removed
- What are the differences between WeakSet and Set?
The main difference is that references to objects in Set are strong while references to objects in WeakSet are weak. i.e, An object in WeakSet can be garbage collected if there is no other reference to it. Other differences are:
What is a WeakMap?
The WeakMap object is a collection of key/value pairs in which the keys are weakly referenced. In this case, keys must be objects and the values can be arbitrary values. The syntax looks like the following:
new WeakMap([iterable]);
Let's see the below example to explain it's behavior:
let wm = new WeakMap(); let user = {}; console.log(wm); // WeakMap {} wm.set(user); console.log( wm.has(user) ); // true wm.delete(user); // removes user from the map console.log( wm.has(user) ); // false, user has been removed
- What are the differences between WeakMap and Map?
The main difference is that references to key objects in Map are strong while references to key objects in WeakMap are weak. i.e, A key object in WeakMap can be garbage collected if there is no other reference to it. Other differences are:
What is an anonymous function?
An anonymous function is a function without a name! Anonymous functions are commonly assigned to a variable name or used as a callback function. The syntax would be as below:
function (optionalParameters) { // do something } // Anonymous function assigned to a variable const myFunction = function() { // do something }; // Anonymous function used as a callback function [1, 2, 3].map(function(element) { // do something });
Let's see the above anonymous function in an example:
let x = function (a, b) { return a * b; }; let z = x(5, 10); console.log(z); // 50
What are JavaScript accessors?
ECMAScript 5 introduced JavaScript object accessors or computed properties through getters and setters. Getters uses the get keyword whereas Setters uses the set keyword.
let user = { firstName: "John", lastName: "Abraham", language: "en", get lang() { return this.language; }, set lang(lang) { this.language = lang; }, }; console.log(user.lang); // getter access lang as en user.lang = "fr"; console.log(user.lang); // setter used to set lang as fr
- What are the advantages of Getters and Setters?
Below are the list of benefits of Getters and Setters:
What is an Error object?
An error object is a built in error object that provides error information when an error occurs. It has two properties: name and message. For example, the below function logs error details:
try { greeting("Welcome"); } catch (err) { console.log(`Error name: ${err.name}, Error message: ${err.message}`); } // Error name: ReferenceError, Error message: greeting is not defined
- What are the different error names from Error object?
There are 7 different types of error names returned from error object:
- What are the various statements in Error handling?
What is an Event Loop?
The Event Loop is a process that continuously monitors both the Call Stack and the Event Queue and checks whether or not the call stack is empty.
If the Call Stack is empty and there are pending events in the Event Queue, the Event Loop dequeues the event from the Event Queue and pushes it to the Call Stack. The Call Stack executes the event, and any additional events generated during the execution are added to the end of the Event Queue.
Note: The Event Loop allows Node.js to perform non-blocking I/O operations, even though JavaScript is single-threaded, by offloading operations to the system kernel whenever possible. Since most modern kernels are multi-threaded, they can handle multiple operations executing in the background.
What is Call Stack?
Call Stack is a data structure for JavaScript interpreters to keep track of function calls (creates execution context) in the program. It has two major actions:
Let's take an example:
function hungry() { eatFruits(); } function eatFruits() { return "I'm eating fruits"; } // Invoke the `hungry` function hungry();
The above code processed in a Call Stack as below:
What is an Event Queue?
The Event Queue follows the queue data structure. It stores async callbacks to be added to the Call Stack. It is also known as the Callback Queue or Macrotask Queue.
Whenever the Call Stack receives an async function, it is moved into the Web API. Based on the function, Web API executes it and awaits the result. Once it is finished, it moves the callback into the Event Queue (the callback of the promise is moved into the Microtask Queue).
The Event Loop constantly checks whether or not the Call Stack is empty. Once the Call Stack is empty and there is a callback in the Event Queue, the Event Loop moves the callback into the Call Stack. But if there is a callback in the Microtask Queue as well, it is moved first. The Microtask Queue has a higher priority than the Event Queue.
What is Obfuscation in JavaScript?
Obfuscation is the deliberate act of creating obfuscated JavaScript code (i.e, source or machine code) that is difficult for humans to understand. It is something similar to encryption, but a machine can understand the code and execute it. Let's see the below function before Obfuscation:
function greeting() { console.log("Hello, welcome to JS world!"); } greeting(); // Hello, welcome to JS world!
And after the code Obfuscation, it would be appeared as below:
function _0x24f5(_0x12c6c6,_0x3c8c6f){var _0x35ab76=_0x35ab();return _0x24f5=function(_0x24f505,_0x114ded){_0x24f505=_0x24f505-0xb3;var _0xe4a297=_0x35ab76[_0x24f505];return _0xe4a297;},_0x24f5(_0x12c6c6,_0x3c8c6f);}function _0x35ab(){var _0x4c11ef=['147vBpgYW','1241064chRVDh','249210bYyZWo','Hello,\x20welcome\x20to\x20JS\x20world!','1562582dNyszE','log','1428975oDRQKP','33441876VnENFa','878600hGEyGy','14804VgAulD','515KCoTPv'];_0x35ab=function(){return _0x4c11ef;};return _0x35ab();}(function(_0x4299dd,_0xc9fdf5){var _0xf6274f=_0x24f5,_0x4cf9f5=_0x4299dd();while(!![]){try{var _0x97dd5b=-parseInt(_0xf6274f(0xbd))/0x1+-parseInt(_0xf6274f(0xb5))/0x2+parseInt(_0xf6274f(0xb7))/0x3+parseInt(_0xf6274f(0xba))/0x4*(-parseInt(_0xf6274f(0xbb))/0x5)+-parseInt(_0xf6274f(0xb3))/0x6*(parseInt(_0xf6274f(0xbc))/0x7)+-parseInt(_0xf6274f(0xb9))/0x8+parseInt(_0xf6274f(0xb8))/0x9;if(_0x97dd5b===_0xc9fdf5)break;else _0x4cf9f5['push'](_0x4cf9f5['shift']());}catch(_0x4c9047){_0x4cf9f5['push'](_0x4cf9f5['shift']());}}}(_0x35ab,0xc4e47));function greeting(){var _0x2e12a6=_0x24f5;console[_0x2e12a6(0xb6)](_0x2e12a6(0xb4));}greeting();
What is Minification?
Minification is the process of removing all unnecessary characters (empty spaces are removed) and variables will be renamed without changing it's functionality. It is also a type of obfuscation.
- What are the advantages of minification?
Normally it is recommended to use minification for heavy traffic and intensive requirements of resources. It reduces file sizes with below benefits:
Does JavaScript supports namespace?
JavaScript doesn't support namespace by default. So if you create any element (function, method, object, variable) then it becomes global and pollutes the global namespace. Let's take an example of defining two functions without any namespace:
function func1() { console.log("This is a first definition"); } function func1() { console.log("This is a second definition"); } func1(); // This is a second definition
It always calls the second function definition. In this case, namespace will solve the name collision problem.
- How do you declare namespace?
Even though JavaScript lacks namespaces, we can use Objects , IIFE to create namespaces.
Using Object Literal Notation: Let's wrap variables and functions inside an Object literal which acts as a namespace. After that you can access them using object notation:
let namespaceOne = { func1: function() { console.log("This is a first definition"); } }; let namespaceTwo = { func1: function() { console.log("This is a second definition"); } }; namespaceOne.func1(); // This is a first definition namespaceTwo.func1(); // This is a second definition
Using IIFE (Immediately Invoked Function Expression): The outer pair of parentheses of IIFE creates a local scope for all the code inside of it and makes the anonymous function a function expression. Due to that, you can create the same function in two different function expressions to act as a namespace:
(function () { function func1() { console.log("This is a first definition"); } func1(); })(); (function () { function func1() { console.log("This is a second definition"); } func1(); })();
Using a block and a let/const declaration: In ECMAScript 6, you can simply use a block and a let declaration to restrict the scope of a variable to a block:
{ let myFunction = function func1() { console.log("This is a first definition"); }; myFunction(); } // myFunction(): ReferenceError: myFunction is not defined. { let myFunction = function func1() { console.log("This is a second definition"); }; myFunction(); } // myFunction(): ReferenceError: myFunction is not defined.
Why do we call JavaScript as Dynamic Language?
JavaScript is a loosely typed or a dynamic language, because variables in JavaScript are not directly associated with any particular value type, and any variable can be assigned/reassigned with values of all types.
let age = 50; console.log(typeof age); // number age = "old"; console.log(typeof age); // string age = true; console.log(typeof age); // boolean
What is the output of the following for loops?
for (var i = 0; i < 4; i++) { // global scope setTimeout(() => console.log(i)); } for (let i = 0; i < 4; i++) { // block scope setTimeout(() => console.log(i)); }
The output of the above for loops is 4 4 4 4 and 0 1 2 3.
Explanation: Due to the event queue/loop of JavaScript, the setTimeout callback function is called after the loop has been executed. Since the variable i is declared with the var keyword it became a global variable and the value was equal to 4 using iteration when the time setTimeout function is invoked. Hence, the output of the first loop is 4 4 4 4.
Whereas in the second loop, the variable i is declared as the let keyword it becomes a block scoped variable and it holds a new value (0, 1, 2, 3) for each iteration. Hence, the output of the second loop is 0 1 2 3.
List down some of the features of ES6?
ES6 is the sixth edition of the JavaScript language and it was released in June 2015. It was initially known as ECMAScript 6 (ES6) and later renamed to ECMAScript 2015.
Below are the list of some new features of ES6:
What are default parameters?
In ES5, we need to depend on logical OR operators to handle default values of function parameters.
Whereas in ES6, default function parameters feature allows parameters to be initialized with default values if no value or undefined is passed.
Let's compare the behavior with an examples:
// ES5 let calculateArea = function (height, width) { height = height || 5; width = width || 10; return width * height; }; console.log(calculateArea()); // 50
// ES6 let calculateArea = function (height = 5, width = 10) { return width * height; }; console.log(calculateArea()); // 50
What are template literals?
Template literals or template strings are string literals allowing embedded expressions. These are enclosed by the back-tick (`) character instead of double or single quotes. In ES6, this feature enables using dynamic expressions as below:
let greeting = `Welcome to JS World, Mr. ${firstName} ${lastName}.`;
In ES5, you need break string like below:
let greeting = 'Welcome to JS World, Mr. ' + firstName + ' ' + lastName + '.';
Note: You can use multi-line strings and string interpolation features with template literals.
What are nesting templates?
The nesting template is a feature supported within template literals syntax to allow inner backticks inside a placeholder ${ } within the template. For example, the below nesting template is used to display the icons based on user permissions whereas outer template checks for platform type:
let isMobilePlatform = () => false; let user = { isAuthorized: true }; const iconStyles = `icon ${ isMobilePlatform() ? "" : `icon-${user.isAuthorized ? "submit" : "disabled"}` }`; console.log(iconStyles); // icon icon-submit
You can write the above use case without nesting template features as well. However, the nesting template feature is more compact and readable.
let isMobilePlatform = () => false; let user = { isAuthorized: true }; const iconStyles = `icon ${ isMobilePlatform() ? "" : user.isAuthorized ? "icon-submit" : "icon-disabled" }`; console.log(iconStyles); // icon icon-submit
What are tagged templates?
Tagged templates are the advanced form of templates in which tags allow you to parse template literals with a function. The tag function accepts the first parameter as an array of strings and remaining parameters as expressions.
This function can also return manipulated strings based on parameters. Let's see the usage of this tagged template behavior of an IT professional skill set in an organization:
let user1 = "John"; let skill1 = "JavaScript"; let experience1 = 15; let user2 = "Kane"; let skill2 = "JavaScript"; let experience2 = 5; function myInfoTag(strings, userExp, experienceExp, skillExp) { let str0 = strings[0]; // "Mr/Ms. " let str1 = strings[1]; // " is a/an " let str2 = strings[2]; // "in" let expertiseStr; if (experienceExp > 10) { expertiseStr = "expert developer"; } else if (skillExp > 5 && skillExp <= 10) { expertiseStr = "senior developer"; } else { expertiseStr = "junior developer"; } return `${str0}${userExp}${str1}${expertiseStr}${str2}${skillExp}`; } let output1 = myInfoTag`Mr/Ms. ${user1} is a/an ${experience1} in ${skill1}`; let output2 = myInfoTag`Mr/Ms. ${user2} is a/an ${experience2} in ${skill2}`; console.log(output1); // Mr/Ms. John is a/an expert developer in JavaScript console.log(output2); // Mr/Ms. Kane is a/an junior developer in JavaScript
What is destructuring assignment?
The destructuring assignment is a JavaScript expression that makes it possible to unpack values from arrays or properties from objects into distinct variables. Let's get the month values from an array using destructuring assignment:
let [one, two, three] = ["JAN", "FEB", "MARCH"]; console.log(one); // "JAN" console.log(two); // "FEB" console.log(three); // "MARCH"
and you can get user properties of an object using destructuring assignment:
let { name, age } = { name: "John", age: 32 }; console.log(name); // John console.log(age); // 32
What are default values in destructuring assignment?
A variable can be assigned a default value when the value unpacked from the array or object is undefined during destructuring assignment. It helps to avoid setting default values separately for each assignment. Let's take an example for both arrays and object use cases.
- Arrays destructuring:
let x, y, z; [x = 2, y = 4, z = 6] = [10]; console.log(x); // 10 console.log(y); // 4 console.log(z); // 6
- Objects destructuring:
let { x = 2, y = 4, z = 6 } = { x: 10 }; console.log(x); // 10 console.log(y); // 4 console.log(z); // 6
How do you swap variables in destructuring assignment?
If you don't use destructuring assignment, swapping two values requires a temporary variable. Whereas using a destructuring feature, two variable values can be swapped in one destructuring expression. Let's swap two number variables in array destructuring assignment:
let x = 10, y = 20; [x, y] = [y, x]; console.log(x); // 20 console.log(y); // 10
What are enhanced object literals?
Object literals make it easy to quickly create objects with properties inside the curly braces.
For example, it provides shorter syntax for common object property definition as below:
// ES6 let x = 10, y = 20; obj = { x, y }; console.log(obj); // {x: 10, y:20}
// ES5 let x = 10, y = 20; obj = { x: x, y: y }; console.log(obj); // {x: 10, y:20}
What are typed arrays?
Typed arrays are array-like objects from ECMAScript 6 API for handling binary data. JavaScript provides 12 Typed array types:
const a = new Int8Array(); console.log(a); // Int8Array [buffer: ArrayBuffer(0), byteLength: 0, byteOffset: 0, length: 0, Symbol(Symbol.toStringTag): 'Int8Array']
const bytes = 8; const a = new Int8Array(bytes); console.log(a); // Int8Array(8) [0, 0, 0, 0, 0, 0, 0, 0, buffer: ArrayBuffer(8), byteLength: 8, byteOffset: 0, length: 8, Symbol(Symbol.toStringTag): 'Int8Array']
What is collation?
Collation is used for sorting a set of strings and searching within a set of strings. It is parameterized by locale and aware of Unicode. Let's take comparison and sorting features:
- Comparison:
let list = ["ä", "a", "z"]; // In German, "ä" sorts with "a" Whereas in Swedish, "ä" sorts after "z" let l10nDE = new Intl.Collator("de"); let l10nSV = new Intl.Collator("sv"); console.log(l10nDE.compare("ä", "z") === -1); // true console.log(l10nSV.compare("ä", "z") === +1); // true
- Sorting:
let list = ["ä", "a", "z"]; // In German, "ä" sorts with "a" Whereas in Swedish, "ä" sorts after "z" let l10nDE = new Intl.Collator("de"); let l10nSV = new Intl.Collator("sv"); console.log(list.sort(l10nDE.compare)); // [ "a", "ä", "z" ] console.log(list.sort(l10nSV.compare)); // [ "a", "z", "ä" ]
Do all objects have prototypes?
No.
All objects have prototypes except the base object or an object created with Object.create(null) method. The base object is Object.prototype, and its prototype is null.
What is the difference between Shallow and Deep copy?
There are two ways to copy an object:
- Shallow Copy. Shallow copy is a bitwise copy of an object. A new object is created that has an exact copy of the values in the original object. If any of the fields of the object are references to other objects, just the reference addresses are copied i.e., only the memory address is copied.
let empDetails = { name: "John", age: 25, expertise: "Software Developer", }; let empDetailsShallowCopy = empDetails; empDetailsShallowCopy.name = "Johnson"; console.log(empDetails.name); // Johnson console.log(empDetailsShallowCopy.name); // Johnson
The above statement will also change the name of empDetails, since we have a shallow copy. That means we're losing the original data as well.
- Deep copy: A deep copy copies all fields, and makes copies of dynamically allocated memory pointed to by the fields. A deep copy occurs when an object is copied along with the objects to which it refers.
let empDetails = { name: "John", age: 25, expertise: "Software Developer", }; let empDetailsDeepCopy = { name: empDetails.name, age: empDetails.age, expertise: empDetails.expertise, }; empDetailsDeepCopy.name = "Johnson"; console.log(empDetails.name); // John console.log(empDetailsDeepCopy.name); // Johnson
Now if you change empDetailsDeepCopy.name, it will only affect empDetailsDeepCopy, not empDetails.
Does JavaScript uses Mixins?
Mixin is a generic object-oriented programming term - is a class containing methods that can be used by other classes without a need to inherit from it.
In JavaScript we can only inherit from a single object. ie. There can be only one [[prototype]] for an object.
But sometimes we require to extend more than one, to overcome this we can use Mixin which helps to copy methods to the prototype of another class.
Say for instance, we've two classes User and CleanRoom. Suppose we need to add CleanRoom functionality to User, so that user can clean the room at demand. Here's where concept called mixins comes into picture.
// mixin let cleanRoomMixin = { cleanRoom() { console.log(`Hello ${this.name}, your room is clean now!`); }, sayBye() { console.log(`Bye, ${this.name}!`); }, }; // usage: class User { constructor(name) { this.name = name; } } // copy the methods Object.assign(User.prototype, cleanRoomMixin); // now User can clean the room new User("Dude").cleanRoom(); // Hello Dude, your room is clean now! new User("John").sayBye(); // Bye, John!
What is a thunk function?
A thunk is just a function which delays the evaluation of the value. It doesn’t take any arguments but gives the value whenever you invoke the thunk. i.e, It is used not to execute now but it will be sometime in the future. Let's take a synchronous example:
const add = (x, y) => x + y; const thunk = () => add(2, 3); console.log(thunk()); // 5
What are asynchronous thunks?
The asynchronous thunks are useful to make network requests. Let's see an example of network requests:
function fetchData(fn) { fetch("https://jsonplaceholder.typicode.com/todos/1") .then((response) => response.json()) .then((json) => fn(json)); } const asyncThunk = function () { return fetchData(function getData(data) { console.log(data); }); }; asyncThunk(); // {userId: 1, id: 1, title: 'delectus aut autem', completed: false}
The getData function won't be called immediately but it will be invoked only when the data is available from API endpoint. The setTimeout function is also used to make our code asynchronous. The best real time example is Redux State Management library which uses the asynchronous thunks to delay the actions to dispatch.
What is the output of below function calls?
const circle = { radius: 20, diameter() { return this.radius * 2; }, perimeter: () => 2 * Math.PI * this.radius, }; console.log(circle.diameter()); // 40 console.log(circle.perimeter()); // NaN
The output is 40 and NaN. Remember that diameter is a regular function, whereas the value of perimeter is an arrow function. The this keyword of a regular function (i.e, diameter) refers to the surrounding scope which is a class (i.e, Shape object). Whereas this keyword of perimeter function refers to the surrounding scope which is a window object. Since there is no radius property on window objects it returns an undefined value and the multiple of number value returns NaN value.
window.radius = 10; const circle = { radius: 20, diameter() { return this.radius * 2; }, perimeter: () => 2 * Math.PI * this.radius, }; console.log(circle.diameter()); // 40 console.log(circle.perimeter()); // 62.83185307179586
What is the difference between Reflow and Repaint?
A repaint occurs when changes are made which affect the visibility of an element, but not its layout. Examples of this include outline, visibility, or background color.
A reflow involves changes that affect the layout of a portion of the page (or the whole page). Resizing the browser window, changing the font, content changing (such as user typing text), using JavaScript methods involving computed styles, adding or removing elements from the DOM, and changing an element's classes are a few of the things that can trigger reflow.
Reflow of an element causes the subsequent reflow of all child and ancestor elements as well as any elements following it in the DOM.
How do you map the array values without using map method?
You can map the array values without using the map method by just using the from method of Array. Let's map city names from Countries array:
const countries = [ { name: "India", capital: "Delhi" }, { name: "US", capital: "Washington" }, { name: "Russia", capital: "Moscow" }, { name: "Singapore", capital: "Singapore" }, { name: "China", capital: "Beijing" }, { name: "France", capital: "Paris" }, ]; const cityNames = Array.from(countries, ({ capital }) => capital); console.log(cityNames); // ['Delhi, 'Washington', 'Moscow', 'Singapore', 'Beijing', 'Paris']
How do you empty an array?
You can empty an array quickly by setting the array length to zero.
let cities = ["Singapore", "Delhi", "London"]; cities.length = 0; console.log(cities); // []
What is the easiest way to convert an array to an object?
You can convert an array to an object with the same data using spread(...) operator.
let fruits = ["banana", "apple", "orange", "watermelon"]; let fruitsObject = {...fruits}; console.log(fruitsObject); // {0: "banana", 1: "apple", 2: "orange", 3: "watermelon"}
What are the placeholders from console object?
Below are the list of placeholders available from console object:
These placeholders can be represented in the console.log as below:
const user = { name: "John", id: 1, city: "Delhi" }; console.log( "Hello %s, your details %o are available in the object form", "John", user ); // Hello John, your details {name: 'John', id: 1, city: 'Delhi'} are available in the object form
Is it possible to add CSS to console messages?
Yes, you can apply CSS styles to console messages similar to HTML text on the web page.
console.log( "%c The text has blue color, with large font and red background!", "color: blue; font-size: x-large; background: red" );
How do you create copy to clipboard button?
You need to select the content (using .select() method) of the input element and execute the copy command with execCommand (i.e, execCommand('copy')).
You can also execute other system commands like cut and paste.
<input type="text" id="copy-input" value="Some text."> <button id="copy-button">Copy!</button> document.querySelector("#copy-button").onclick = function () { document.querySelector("#copy-input").select(); document.execCommand("copy"); };
What are Wrapper Objects?
Primitive values like string, number and boolean don't have properties and methods but they are temporarily converted or coerced to an object (Wrapper object) when you try to perform actions on them.
For example, if you apply toUpperCase() method on a primitive string value, it does not throw an error but returns uppercase of the string.
let name = "john"; console.log(name.toUpperCase()); // JOHN // Behind the scenes treated as console.log(new String(name).toUpperCase());
What is minimum timeout throttling?
Both browser and NodeJS JavaScript environments throttles with a minimum delay that is greater than 0ms. That means even though setting a delay of 0ms will not happen instantaneously.
Browsers: They have a minimum delay of 4ms. This throttle occurs when successive calls are triggered due to callback nesting (certain depth) or after a certain number of successive intervals. Note: The older browsers have a minimum delay of 10ms.
NodeJS: They have a minimum delay of 1ms. This throttle happens when the delay is larger than 2147483647 or less than 1. The best example to explain this timeout throttling behavior is the order of below code snippet.
function runMeFirst() { console.log("My script is initialized"); } setTimeout(runMeFirst, 0); console.log("Script loaded"); // Script loaded // My script is initialized
If you don't use setTimeout, the order of logs will be sequential:
function runMeFirst() { console.log("My script is initialized"); } runMeFirst(); console.log("Script loaded"); // My script is initialized // Script loaded
How do you detect primitive or non primitive value type?
In JavaScript, primitive types include boolean, string, number, BigInt, null, Symbol and undefined. Whereas non-primitive types include the Objects.
But you can easily identify them with the below function:
let myPrimitive = 30; let myNonPrimitive = {}; function isPrimitive(val) { return Object(val) !== val; } console.log( isPrimitive(myPrimitive) ); // true console.log( isPrimitive(myNonPrimitive) ); // false
If the value is a primitive data type, the Object constructor creates a new wrapper object for the value. But if the value is a non-primitive data type (an object), the Object constructor will give the same object.
What is the difference between function constructor and function declaration?
The functions which are created with function constructor do not create closures to their creation contexts but they are always created in the global scope. i.e, the function can access its own local variables and global scope variables only. Whereas function declarations can access outer function variables (closures) too.
Let's see this difference with an example:
- Function Constructor:
let a = 100; function createFunction() { let a = 200; return new Function("return a;"); } console.log( createFunction()() ); // 100
- Function Declaration:
let a = 100; function createFunction() { let a = 200; return function func() { return a; }; } console.log( createFunction()() ); // 200
What is a short circuit condition?
Short circuit conditions are meant for condensed way of writing simple if statements. Let's demonstrate the scenario using an example. If you would like to login to a portal with an authentication condition, the expression would be as below:
if (authenticate) { loginToPortal(); }
Since the JavaScript logical operators evaluated from left to right, the above expression can be simplified using && logical operator:
authenticate && loginToPorta();
What is the difference between function and class declarations?
The main difference between function declarations and class declarations is hoisting. The function declarations are hoisted but not class declarations.
- Classes:
const user = new User(); // Uncaught ReferenceError: Cannot access 'User' before initialization class User {}
- Constructor Function:
const user = new User(); // No error function User() {}
What is an async function?
An async function is a function declared with the async keyword which enables asynchronous, promise-based behavior to be written in a cleaner style by avoiding promise chains. These functions can contain zero or more await expressions.
Let's take a below async function example:
async function logger() { await fetch('https://jsonplaceholder.typicode.com/todos/1') .then(response => response.json()) .then(json => console.log(json.title)); } logger(); // delectus aut autem
It is basically syntax sugar over ES2015 promises and generators.
What are the different kinds of generators?
There are five kinds of generators:
- Generator function declaration:
function* myGenFunc() { yield 1; yield 2; yield 3; } const genObj = myGenFunc();
- Generator function expressions:
const myGenFunc = function* () { yield 1; yield 2; yield 3; }; const genObj = myGenFunc();
- Generator method definitions in object literals:
const myObj = { *myGeneratorMethod() { yield 1; yield 2; yield 3; }, }; const genObj = myObj.myGeneratorMethod();
- Generator method definitions in class:
class MyClass { *myGeneratorMethod() { yield 1; yield 2; yield 3; } } const myObject = new MyClass(); const genObj = myObject.myGeneratorMethod();
- Generator as a computed property:
const SomeObj = { *[Symbol.iterator]() { yield 1; yield 2; yield 3; }, }; console.log(Array.from(SomeObj)); // [ 1, 2, 3 ]
What are the differences between for...of and for...in statements?
Both for...in and for...of statements iterate over JS data structures. The only difference is over what they iterate:
Let's explain this difference with an example:
let arr = ["a", "b", "c"]; arr.newProp = "newVlue"; console.log(arr); // ['a', 'b', 'c', newProp: 'newVlue'] // key are the property keys for (let key in arr) { console.log(key); // 0, 1, 2, newProp } // value are the property values for (let value of arr) { console.log(value); // a, b, c }
Since for...in loop iterates over the keys of the object, the first loop logs 0, 1, 2 and newProp while iterating over the array object. The for...of loop iterates over the values of arr data structure and logs a, b, c in the console.
How do you define instance and non-instance properties?
The instance properties must be defined inside of class methods. For example, name and age properties defined inside constructor as below:
class Person { constructor(name, age) { this.name = name; this.age = age; } }
But static (class) and prototype data properties must be defined outside of the class body declaration. Let's assign the age value for Person class as below:
Person.staticAge = 30; Person.prototype.prototypeAge = 40;
class Person { constructor(name, age) { this.name = name; this.age = age; } } Person.staticAge = 30; Person.prototype.prototypeAge = 40; let john = new Person('John', 25); console.log(john.age); // 25 console.log(john.staticAge); // undefined console.log(john.prototypeAge); // 40 console.log(Person.staticAge); // 30 console.log(Person.prototypeAge); // undefined
How to invoke an IIFE without any extra brackets?
Immediately Invoked Function Expressions (IIFE) requires a pair of parenthesis to wrap the function which contains set of statements.
(function (dt) { console.log(dt.toLocaleTimeString()); })(new Date()); // 12:14:37 PM
Since both IIFE and void operator discard the result of an expression, you can avoid the extra brackets using void operator for IIFE as below:
void function (dt) { console.log(dt.toLocaleTimeString()); }(new Date()); // 12:14:37 PM
What is the easiest way to ignore promise errors?
The easiest and safest way to ignore promise errors is void that error. This approach is ESLint friendly too.
await promise.catch((e) => void e);
What is nullish coalescing operator?
It is a logical operator that returns its right-hand side operand when its left-hand side operand is null or undefined, and otherwise returns its left-hand side operand.
This can be contrasted with the logical OR (||) operator, which returns the right-hand side operand if the left operand is any falsy value, not only null or undefined.
console.log(null ?? true); // true console.log(undefined ?? true); // true console.log(false ?? true); // false console.log('' ?? true); // ''
What is the difference between dense and sparse arrays?
An array contains items at each index starting from first(0) to last(array.length - 1) is called as dense array. Whereas if at least one item is missing at any index, the array is called as sparse.
Let's see the below two kind of arrays:
const avengers = ["Ironman", "Hulk", "Captain America"]; console.log(avengers[0]); // Ironman console.log(avengers[1]); // Hulk console.log(avengers[2]); // Captain America console.log(avengers.length); // 3 const justiceLeague = ["Superman", "Aquaman", , "Batman"]; console.log(justiceLeague[0]); // Superman console.log(justiceLeague[1]); // Aquaman console.log(justiceLeague[2]); // undefined console.log(justiceLeague[3]); // Batman console.log(justiceLeague.length); // 4
What are the different ways to create sparse arrays?
There are 4 different ways to create sparse arrays in JavaScript:
- Array literal. Omit a value when using the array literal:
const justiceLeague = ["Superman", "Aquaman", , "Batman"]; console.log(justiceLeague); // (4) ['Superman', 'Aquaman', empty, 'Batman']
- Array() constructor. Invoking Array(length) or new Array(length):
const array = Array(3); console.log(array); // (3) [empty × 3]
- Delete operator. Using delete array[index] operator on the array:
const justiceLeague = ["Superman", "Aquaman", "Batman"]; delete justiceLeague[1]; console.log(justiceLeague); // (3) ['Superman', empty, 'Batman']
- Increase length property. Increasing length property of an array:
const justiceLeague = ["Superman", "Aquaman", "Batman"]; justiceLeague.length = 5; console.log(justiceLeague); // (5) ['Superman', 'Aquaman', 'Batman', empty × 2]
How do you create custom HTML element?
The creation of custom HTML elements involves two main steps:
- Define your custom HTML element. First you need to define some custom class by extending HTMLElement class. After that define your component properties (styles, text etc.) using connectedCallback method.
class CustomElement extends HTMLElement { connectedCallback() { this.innerHTML = "This is a custom element"; } } customElements.define("custom-element", CustomElement);
- Use custom element just like other HTML element. Declare your custom element as a HTML tag.
<custom-element>
What is global execution context?
The global execution context is the default or first execution context that is created by the JavaScript engine before any code is executed (i.e, when the file first loads in the browser). All the global code that is not inside a function or object will be executed inside this global execution context. Since JS engine is single threaded there will be only one global environment and there will be only one global execution context.
For example, the below code other than code inside any function or object is executed inside the global execution context.
let x = 10; function A() { console.log("Start function A"); function B() { console.log("In function B"); } B(); } A(); console.log("GlobalContext"); // Start function A // In function B // GlobalContext
What is function execution context?
Whenever a function is invoked, the JavaScript engine creates a different type of Execution Context known as a Function Execution Context (FEC) within the Global Execution Context (GEC) to evaluate and execute the code within that function.
What is optional chaining?
The optional chaining operator (?.) permits reading the value of a property located deep within a chain of connected objects without having to expressly validate that each reference in the chain is valid.
The ?. operator is like the . chaining operator, except that instead of causing an error if a reference is nullish (null or undefined), the expression short-circuits with a return value of undefined. When used with function calls, it returns undefined if the given function does not exist.
const adventurer = { name: "Alice", cat: { name: "Dinah", }, }; const dogName = adventurer.dog?.name; console.log(dogName); // undefined console.log(adventurer.someNonExistentMethod?.()); // undefined
What is pass by value and pass by reference?
Pass-by-value creates a new space in memory and makes a copy of a value. Primitives such as string, number, boolean etc. will actually create a new copy. Hence, updating one value doesn't impact the other value. i.e, the values are independent of each other.
let a = 5; let b = a; b++; console.log(a, b); // 5 6
In the above code snippet, the value of a is assigned to b and the variable b has been incremented. Since there is a new space created for variable b, any update on this variable doesn't impact the variable a.
Pass by reference doesn't create a new space in memory but the new variable adopts a memory address of an initial variable. Non-primitives such as objects, arrays and functions gets the reference of the initiable variable. i.e, updating one value will impact the other variable.
let user1 = { name: "John", age: 27, }; let user2 = user1; user2.age = 30; console.log(user1.age, user2.age); // 30 30
In the above code snippet, updating the age property of one object will impact the other property due to the same reference.
What are the differences between primitives and non-primitives?
JavaScript language has both primitives and non-primitives but there are few differences between them as below.
- Primitives:
- Non-primitives:
What is referential transparency?
An expression in JavaScript that can be replaced by its value without affecting the behaviour of the program is called referential transparency. Pure functions are referentially transparent.
const add = (x, y) => x + y; const multiplyBy2 = (x) => x * 2; // Now add (2, 3) can be replaced by 5. console.log( multiplyBy2(add(2, 3)) ); // 10
What is module pattern?
Module pattern is a designed pattern used to wrap a set of variables and functions together in a single scope returned as an object. JavaScript doesn't have access specifiers similar to other languages (Java, Python, etc.) to provide private scope. It uses IIFE (Immediately Invoked Function Expression) to allow for private scopes. i.e., a closure that protect variables and methods.
The module pattern looks like below:
(function () { // Private variables or functions goes here. return { // Return public variables or functions here. }; })();
Let's see an example of a module pattern for an employee with private and public access:
const createEmployee = (function () { // Private const name = "John"; const department = "Sales"; const getEmployeeName = () => name; const getDepartmentName = () => department; // Public return { name, department, getName: () => getEmployeeName(), getDepartment: () => getDepartmentName(), }; })(); console.log(createEmployee.name); // John console.log(createEmployee.department); // Sales console.log(createEmployee.getName()); // John console.log(createEmployee.getDepartment()); // Sales
Note: It mimic the concepts of classes with private variables and methods.
What is Function Composition?
It is an approach where the result of one function is passed on to the next function, which is passed to another until the final function is executed for the final result.
const double = (x) => x * 2; const square = (x) => x * x; let output1 = double(2); let output2 = square(output1); console.log(output2); // 16 let output_final = square(double(2)); console.log(output_final); // 16
What is the purpose of the this keyword in JavaScript?
The this keyword in JavaScript is a special variable that is used within a function to refer to the object on which the function is invoked. The value of this depends on how the function is called. It allows functions to access and interact with the object they are bound to.
The this keyword in JavaScript is a reference to the object that owns or invokes the current function. Its value is determined by the calling context.
- this in a Global Context
console.log(this); // Window {window: Window, self: Window, document: document, name: '', location: Location, ...}
In a global context, this refers to the global object (e.g., window in a browser).
- this in a Function
function displayThis() { console.log(this); } displayThis(); // Window {window: Window, self: Window, document: document, name: '', location: Location, ...}
In a regular function, this refers to the global object.
- this in a Method
let globalAge = 25; const person = { name: 'John', greet: function() { console.log(`Hello, ${this.name}!`); }, age1: function() { console.log(this.globalAge); }, age2: function() { console.log(globalAge); } }; person.greet(); // Hello, John! person.age1(); // undefined person.age2(); // 25
In a method, this refers to the object that owns the method (person in the case).
- this in an Event Handler
document.getElementById('myButton').addEventListener('click', function() { console.log(this); });
In an event handler, this refers to the element that triggered the event (the button in this case).
What are the uses of Closures?
Closures are a powerful feature in programming languages like JavaScript. They allow functions to retain access to variables from their containing (enclosing) scope even after the outer function has finished executing. This means that a function defined within another function can access variables from the outer function, even if the outer function has already returned. Here are some common use cases of closures:
What are the phases of Execution Context?
The execution context in JavaScript is a data structure that stores the information necessary for executing a piece of code. It includes the code itself, the values of the variables used in the code, and the scope chain. The scope chain is a list of objects that are used to resolve variable names.
The execution context has two phases:
The execution context is created when a function is called. The function's code is then executed in the execution context. When the function returns, the execution context is destroyed.
What are the possible reasons for Memory Leaks?
Memory leaks can lead to poor performance, slow loading times and even crashes in web applications. Some of the common causes of memory leaks are listed below:
What are the event phases of a browser?
There are 3 phases in the lifecycle of an event propagation in JavaScript.
What are hidden classes?
Since JavaScript is a dynamic programming language, you can add or remove properties and methods from objects on the fly at runtime. This nature of JavaScript increases the dynamic dictionary lookups (because objects implemented as hash tables in memory) for retrieving a property on an object.
Let's consider the following example to see how the additional properties age and gender added at runtime.
function Person(name) { this.name = name; } let person1 = new Person('John'); let person2 = new Person('Randy'); person1.age = 40; person1.gender = "Male"; person2.gender = "Female"; person2.age = 50;
As a result, this behavior leads to lower JavaScript performance compared to the contiguous buffer method used in non-dynamic languages. The V8 engine provided a solution named hidden classes to optimize the access time when retrieving a property on an object. This optimization is achieved by sharing hidden classes among objects created in a similar fashion. These hidden classes are attached to each and every object to track its shape.
When V8 engine sees the constructor function (e.g, Person) is declared, it creates a hidden class (let's say Class01) without any offsets. Once the first property assignment statement (this.name = name) is executed, V8 engine will create a new hidden class (let's say Class02), inheriting all properties from the previous hidden class (Class01), and assign the property to offset 0. This process enables compiler to skip dictionary lookup when you try to retrieve the same property (i.e, name). Instead, V8 will directly point to Class02. The same procedure happens when you add new properties to the object.
For example, adding age and gender properties to Person constructor leads to transition of hidden classes (Class02 -> Class03 -> Class04). If you create a second object (Person2) based on the same Person object, both Class01 and Class02 hidden classes are going to be shared. However, the hidden classes Class03 and Class04 cannot be shared because second object has been modified with a different order of properties assignment.
Since both the objects (person1 and person2) do not share the hidden classes, now V8 engine cannot use inline caching technique for the faster access of properties.
What is inline caching?
Inline caching is an optimization technique based on the observation that repeated calls to same function tends to occur on same type of objects. The V8 compiler stores a cache of the type of objects that were passed as a parameter in recent method calls. Upon next time when same function is called, compiler can directly search for the type in cache.
Let's consider an example where the compiler stores the shape type in cache for repeated calls in the loop.
let shape = { width: 30, height: 20 }; // Compiler store the type in cache as { width: <int>, height: <int>} after repeated calls function area(obj) { //Calculate area } for (let i = 0; i < 100; i++) { area(shape); }
After few successful calls of the same area method to its same hidden class, V8 engine omits the hidden class lookup and simply adds the offset of the property to the object pointer itself. As a result, it increases the execution speed.
There are mainly 3 types of inline caching possible:
What are the different ways to execute external scripts?
There are three different ways to execute external scripts.
async. The script is downloaded in parallel to parsing the page, and executed as soon as it is available even before parsing completes. The parsing of the page is going to be interuppted once the script is downloaded completely and then the script is executed. Thereafter, the parsing of the remaining page will continue.
The syntax for async usage is as shown below:
<script src="demo.js" async></script>
defer. The script is downloaded in parallel to parsing the page, and executed after the page has finished parsing.
The syntax for defer usage is as shown below:
<script src="demo.js" defer></script>
Neither async or defer. The script is downloaded and executed immediately by blocking parsing of the page until the script execution is completed.
What is globalThis, and what is the importance of it?
Nowadays JavaScript language is used in a wide variety of environments and each environment has its own object model. Due to this fact, there are different ways (syntax) to access the global object.
The globalThis property provides a standard way of accessing the global object without writing various code snippet to support multiple environments. For example, the global object retuned from multiple environments as shown below:
// Browser environment console.log(globalThis); // => Window {...} // NodeJS environment console.log(globalThis); // => Object [global] {...} // Web Worker environment console.log(globalThis); // => DedicatedWorkerGlobalScope {...}
test