Navigation
- JavaScript Basics
- Variables & Data types
- Functions & Loops
- Objects & Arrays
- Prototypes, inheritance and this
- Sources / Literature
JavaScript Basics
1. What is the javascript? - Answer
2. What is the Scope? - Answer
3. What is an Event Loop? How does it work? - Answer
Variables & Data types
1. What declaring variables does JavaScript have? What is the difference between them?
var
: var was the original way to declare variables in JavaScript before ES6. Variables declared with var have function scope or global scope if declared outside a function. They can be redeclared and updated.let
: Introduced in ES6, let allows block-scoped variables. Variables declared with let are limited to the block (enclosed by curly braces) in which they are defined. They cannot be redeclared in the same scope but can be updated.const
: Also introduced in ES6, const is used to declare constants whose values cannot be re-assigned or re-declared. const variables are block-scoped and must be initialized at the time of declaration.
2. What are the various data types that exist in JavaScript? -
There are eight data types that are present in JavaScript:
- String
- Number
- Boolean
- Object
- Null
- Undefined
- BigInt
- Symbol
3. What is the difference between null
and undefined
?
The undefined
usually occurs as a default value in JavaScript, representing the absence of an assigned value, while null
is explicitly set by the programmer to indicate a deliberate absence of a value. Both null
and undefined
are distinct types in JavaScript, but they are often used interchangeably to signify absence or lack of a meaningful value.
4. How to check the type of some operand? What types have the following operands: null
, undefined
, []
and NaN
?
For type checking a type, use typeof
operator that returns a string indicating the type of the operand's value.
console.log(typeof null) // object
console.log(typeof undefined) // undefined
console.log(typeof NaN) // number
console.log(typeof []) // object
5. What limitations have numbers in JavaScript and how to overcome them?
JavaScript as most programming languages has problems with math and huge/small numbers, which all come from the hardware itself. As a result, we get some strange behavior in our codebase e.g.
console.log(0.1 + 0.2); // Output: 0.30000000000000004 (rounded due to precision)
console.log(9007199254740992); // Output: 9007199254740992 (accurate)
console.log(9007199254740993); // Output: 9007199254740992 (loss of precision)
Precision and Representation:
JavaScript numbers are stored as 64-bit floating-point numbers, limiting their range. Numbers outside the range of ±(2^53 - 1) may not be represented accurately.
JavaScript uses the IEEE 754 standard for representing numbers, which can lead to precision issues with floating-point arithmetic. This can cause unexpected behavior when performing calculations involving decimals due to limited precision.
In practice when we work with huge/small and decimal numbers, we are required to mind Number.MAX_SAFE_INTEGER
and Number.MIN_SAFE_INTEGER
edges. if the number exceeds them use BigInt instead of regular numbers. For decimals, we can be used in-build Math functions to get the required results.
const bigIntNum = 123456789012345678901234567890n; // Using the "n" suffix
const anotherBigInt = BigInt("9007199254740993"); // Creating from a string using BigInt()
///
const result = 0.1 + 0.2;
const fixedResult = (result).toFixed(1); // Round to one decimal place
console.log(parseFloat(fixedResult)); // Output: 0.3
Functions & Loops
1. Name ways of declaring functions and their differences in JavaScript?
- Function declaration The function declaration uses the keyword function to declare a function, this method allows to use function before it is defined e.g.
doSomething()
function doSomething () {
//...some actions
}
- Function Expression The assigning a function to some variable, in this case, if the function is called before the declaration causes the ReferenceError
doSomething() //output: ReferenceError
const doSomething = function () {
console.log("Function Expression worked")
}
doSomething() // output: "Function Expression worked"
2. What are arrow functions, How are they different from regular functions and where should use them?
The arrow functions are a concise way to write functions in JavaScript introduced in ES6 (ECMAScript 2015) with a more compact syntax compared to regular functions. They differ from regular functions in a few ways:
- use
=>
to define a function; - do not have its own
this
context; they inheritthis
from the surrounding code; - do not have the
arguments
object;
Can be used as callbacks inside promises, as short anonymous functions inside array methods, where you want to preserve the lexical scope of this
Examples:
//With many arguments:
const doSomething = (a, b) => {return a + b};
//With instant return:
const doSomething = (a, b) => a + b;
//With one argument:
const doSomething = a => a + 1;
//Inside array:
const sum = [1, 2, 3].reduce((acc, cur) => acc + cur, 0);
//Inside promise
fetch('https://some-api').then(res => res.json());
3. What IIFE stands for and where should be used?
IIFE stands for "Immediately Invoked Function Expression."
An IIFE is a JavaScript design pattern that involves defining and immediately executing a function. It is constructed by enclosing the function within parentheses ( ) to create a function expression and then adding an additional set of parentheses ( ) immediately after to invoke the function e.g.
(function() {
// Function body
})();
(() => {
// Function body
})()
Use cases for IIFE:
Encapsulation: IIFEs are commonly used to create a new scope, preventing variable declarations from polluting the global scope. This helps avoid naming conflicts and keeps variables private.
Initialization: They are useful for initializing code that should run once when the script loads, setting up configurations, or executing setup tasks.
Module Patterns: IIFEs are a building block for various module patterns in JavaScript, like the revealing module pattern or module encapsulation, allowing the creation of private variables and functions while exposing only necessary functionalities.
4. What is closure in JavaScript and how it works?
In JavaScript, a closure is a combination of a function and the lexical environment within which that function was declared. Closures allow functions to access and utilize variables from their outer scope even after the outer scope has finished executing.
Here's how closures work:
Lexical Scoping: JavaScript uses lexical scoping, which means that functions can access variables defined in their outer scope at the time they were created, regardless of where they are called from.
Function within a Function: When a function is defined inside another function, the inner function has access to the outer function's variables and parameters, forming a closure.
Preservation of the Outer Scope: Closures "remember" the variables from their outer scope even after the outer function has finished executing. This allows the inner function to maintain access to those variables.
const mainFunction = () => {
const arr = [];
return (value) => {
arr.push(value);
console.log(arr)
}
}
const returnedFunction = mainFunction();
returnedFunction("1") // will console ["1"];
returnedFunction("2") // will console ["1", "2"]
5. What is the anonymous function?
An anonymous function in JavaScript is a function that does not have a name assigned to it. Instead of being declared with a specific identifier (name), it is created inline without a name reference. These functions are often used as callbacks or function expressions where the function itself doesn't need to be named or referenced elsewhere in the code.
const myFunction = function() {
console.log('This is an anonymous function');
};
// Using an anonymous function as a callback
setTimeout(function() {
console.log('This function will execute after 1 second');
}, 1000);
Objects & Arrays
1. Is the one {}
equal another {}
? How to compare two objects?
In JavaScript, when comparing two objects using the equality operators (==
or ===
), these operators check for equality by comparing the references to the objects, not their contents.
const objA = { a: 1, b: 2, c: 3 };
const objB = { a: 1, b: 2, c: 3 };
console.log(objA === objB); // false
Actually, there are several ways to compare objects in JavaScript. The first that may come to mind is to iterate through keys and values and compare them that will look something like:
function isEqual(obj1, obj2) {
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) {
return false;
}
for (const key of keys1) {
if (obj1[key] !== obj2[key]) {
return false;
}
}
return true;
}
const objA = { a: 1, b: 2, c: 3 };
const objB = { a: 1, b: 2, c: 3 };
console.log(isEqual(objA, objB)); // true
Also we can transform objects to JSON strings and compare them like:
const objA = { a: 1, b: 2, c: 3 };
const objB = { a: 1, b: 2, c: 3 };
const stringA = JSON.stringify(objA);
const stringB = JSON.stringify(objB);
console.log(stringA === stringB); // true
Or to use some third-party libs like isEqual
from lodash.
2. How to copy an Object in JavaScript?
There are a several ways to copy an Object in JavaScript:
Object.assign()
: Creates a shallow copy of an object. Copies enumerable own properties from one or more source objects to a target object. Modifies the target object and returns it. Non-enumerable properties and properties on the prototype chain are not copied.
const originalObject = { a: 1, b: 2 };
const copiedObject = Object.assign({}, originalObject);
Spread syntax (...)
: Creates a shallow copy of an object. Copies enumerable own properties from the source object(s) to the new object. Can be used to merge objects or create new objects with copied properties. Similar to Object.assign()
, it doesn't deeply clone nested objects or handle non-enumerable properties.
const originalObject = { a: 1, b: 2 };
const copiedObject = { ...originalObject };
JSON.stringify() and JSON.parse()
: Creates a deep copy of an object but works only with JSON-safe data. Converts the object to a JSON string and then parses it back into a new object. Loses reference to functions, non-JSON-safe objects (like Date objects), and non-enumerable properties.
const originalObject = { a: 1, b: 2 };
const copiedObject = JSON.parse(JSON.stringify(originalObject));
Object.create()
: Creates a new object with the specified prototype object and properties. Allows for setting the prototype of the new object explicitly. Can copy properties from another object, but doesn't create a direct copy of the source object's properties.
const originalObject = { a: 1, b: 2 };
const copiedObject = Object.create(Object.getPrototypeOf(originalObject), Object.getOwnPropertyDescriptors(originalObject));
3. How to check that an object has property?
Using the in
operator, however, it also returns true if the object's prototype has this property. The second approach uses hasOwnProperty()
method on an object.
const proto_obj = {
name: 'user'
};
const obj = {
color: 'red'
}
obj.__proto__ = proto_obj;
console.log('color' in obj); // true
console.log('name' in obj); // true
console.log(obj.hasOwnProperty("color")) // true
console.log(obj.hasOwnProperty("name")) // false
Prototypes, inheritance and this
1. What is a prototype in JavaScript? How to work with it?
In JavaScript, everything is basically primitive or an object. Objects on the other hand have a prototype. The prototype is a reference to another object that the current object inherits properties and methods from. It forms the basis for JavaScript's prototypal inheritance.
2. How to check that an object has property?
Using the in
operator, however, it also returns true if the object's prototype has this property. The second approach uses hasOwnProperty()
method on an object.
const proto_obj = {
name: 'user'
};
const obj = {
color: 'red'
}
obj.__proto__ = proto_obj;
console.log('color' in obj); // true
console.log('name' in obj); // true
console.log(obj.hasOwnProperty("color")) // true
console.log(obj.hasOwnProperty("name")) // false
3. Explain the this
keyword, and how it works?
In JavaScript, the this
keyword is a special identifier that refers to the current instance of an object or the context in which a function is invoked. The value of this is determined by how a function is called or how an object is accessed.
Here are some examples of usages this:
- When used inside a function, this depends on how the function is called. If the function is a regular function (not a method of an object or part of a class),
this
refers to the global object (or undefined in strict mode).
function myFunction() {
console.log(this);
}
myFunction(); // global object | window
- When used inside a method (a function that is a property of an object),
this
refers to the object on which the method is called.
const myObject = {
myMethod: function() {
console.log(this);
}
};
myObject.myMethod(); // Points to myObject
- When used inside a constructor function (a function called with the new keyword to create an instance),
this
refers to the newly created instance.
function MyClass() {
this.myProperty = 42;
}
const myInstance = new MyClass();
console.log(myInstance.myProperty); // 42
- In event handlers,
this
often refers to the DOM element that triggered the event.
document.getElementById('myButton').addEventListener('click', function() {
console.log(this); // Points to the clicked button element
});
4. What is call()
, apply()
and bing()
?
The call()
, apply()
, and bind()
methods are used to explicitly set the value of this
for a function. They allow you to control the context in which a function is executed. These methods are often used in situations where the default behavior of this
is not sufficient, such as when you want to invoke a function with a specific object as its context.
Usage examples:
const obj1 = { name: 'Object 1' };
function sayHello(greeting) {
console.log(`${greeting}, ${this.name}`);
}
sayHello.call(obj1, 'Hello'); // Outputs: Hello, Object 1
const obj2 = { name: 'Object 2' };
function sayHi(greeting) {
console.log(`${greeting}, ${this.name}`);
}
sayHi.apply(obj2, ['Hi']); // Outputs: Hi, Object 2
const obj3 = { name: 'Object 3' };
function greet(greeting) {
console.log(`${greeting}, ${this.name}`);
}
const boundFunction = greet.bind(obj3, 'Greetings');
boundFunction(); // Outputs: Greetings, Object 3
Other (For now)
1. What is the difference between ==
and ===
?
In JavaScript, == (equality operator) and === (strict equality operator) are used for comparison, but they differ in how they evaluate values:
console.log(1 == '1') // true
console.log(1 === '1') // false
2. What is the difference between LocalStorage, SessionStorage та cookies?
LocalStorage is a web storage API in web browsers that allows for persistent storage of key-value pairs in the browser with no expiration date, remaining stored even after the browser is closed.
SessionStorage is another web storage API that stores data in the browser for the duration of the page session, clearing the data when the session ends or the browser is closed.
Cookies are small pieces of data sent from a website and stored in the user's browser, capable of holding limited information and having expiration dates, often used for tracking, authentication, and personalization purposes.
3. What is the difference between for..of and for...in ?
for...of is used for iterating over values of iterable objects like arrays and strings.
for...in is used for iterating over keys or property names of objects, including inherited properties in the prototype chain.
4. What is Map & Set? When it should be used?
Map: A Map is a collection of key-value pairs where each key can be of any data type, including objects or primitive values. It maintains the insertion order of its elements, and keys can be iterated in the order of their insertion. It allows storing unique keys and offers various methods to interact with the data, such as
set()
,get()
,delete()
,has()
, etc. Use Map when you need to associate keys with values, especially when the keys are not simple strings or when you want to maintain the insertion order of key-value pairs. It's useful for scenarios where a unique identifier (key) is associated with some data (value).Set: A Set is a collection of unique values, where each value must be unique within the set. It does not allow duplicate elements, and it also maintains the insertion order of elements. It provides methods like
add()
,delete()
,has()
, etc., to manage and interact with the set. Use Set when you need to maintain a collection of unique values and you want to ensure that each element appears only once within the collection. It's useful for removing duplicates from arrays, managing unique values, or checking for the existence of elements efficiently without needing to manage uniqueness manually.
5. How is asynchronous code executed in JavaScript?
In JavaScript, asynchronous code is executed using an event-driven, non-blocking model. When an asynchronous operation is initiated (such as fetching data from a server or setting a timer), it gets queued in the event loop, allowing the main execution thread to continue processing other tasks. Once the asynchronous operation is completed or ready, its associated callback function or promise is placed in the callback queue. The event loop continuously checks for completed tasks in the callback queue and executes their corresponding callback functions, allowing the program to handle asynchronous tasks without blocking the main thread, ensuring responsiveness in applications.
6. What are the three phases of event propagation?
Capturing > Target > Bubbling. During the capturing phase, the event goes through the ancestor elements down to the target element. It then reaches the target element, and bubbling begins.
Top comments (1)
Very detailed article