Vanilla + ES6 Flashcards

1
Q

Explain the difference between let, const, and var.

A

Scoping rules: variables declared by ‘var’ keyword is scoped to immediate function body (function scope) while ‘let’ & ‘const’ variables are scored to the immediate enclosing block (block scope)

Hoisting: variables declared with ‘var’ keyword are hoisted (initialized with undefined before the code runs) which means they are accessible in their enclosing scope even before they are declared. ‘let’ variables are not initialized until their definition is evaluated. Accessing them before the initialization results in a ‘ReferenceError’. The variable is said to be in a “temporal dead zone” from the start of the block until the initialization is processed.

Re-declaration: in strict mode, var will let you re-declare the same variable in the same scope while let raises a SyntaxError.

Global object property: At the top level, let unlike var does not create a property on the global (window) object

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

What are arrow functions in ES6? How do they differ from traditional function expressions?

A

New ES6 syntax for writing JS functions; simplies function scope.

Key Difference
Syntax:
- Arrow functions shorter syntax
- simplifies the function and return keywork

this keyword:
- this represents the object that called the function
- traditional functions: this gets rescoped to wherever it’s called so it could be the window, document, button or whatever.
- arrow functions: do not have their own this, they inherit it from the parent scope.

Argument object:
- Traditional functions have arguments object which contains all the args passed to the function. Arrow does not but we can still use Rest parameters (…) to achieve a similar outcome.

Constructors:
- Traditional functions created with function declarations or expressions can be used as constructors (i.e., they can be instantiated with the new keyword). Arrow functions, however, cannot be used as constructors, and will throw an error when used with new.

Implicit Return:
- If the function body of an arrow function is written in one line and does not include curly braces, the value is implicitly returned without needing the return keyword.

Method properties:
- Arrow functions are not suitable to be used as object methods, as this will not be bound to the object. Traditional functions are suitable for this use case.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Can you explain what destructuring is in ES6 and provide an example of how it can be used?

A

Provides a simple way to unpack values from arrays, or properties from objects, into distinct variables. Also works in function parameters.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Describe how this keyword works in JavaScript. How does it behave differently in arrow functions compared to regular functions?

A

In JS, the this keywork is a special property that refers to the CONTEXT in which a function is called. It’s pretty tricky because what this refers to can change depending on how and where it’s used.

Global context: this refers to the global object (window object)

Function context: inside a regular function (not arrow, object method, or event handler), this refers to the window or global object if not in strict mode. Otherwise undefined.

Method context: this refers to the object that the method belongs to.

Event handler context: this refers to the element that received the event.

Constructor context: this refers to the newly created object

Manually set context: we can set value of this using the call, apply or bind methods.

Arrow function context: they don’t have their own this so they inherit it from the parent scope => more predictable => easier to use for callbacks and event handlers.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

What is a Promise in JavaScript? Can you describe a scenario where it would be useful?

A

An object representing the eventual completion or failure of an asynchronous operation. It’s basically a proxy for a value not necessarily known when the promise is created. It’s one way to deal with async operations without blocking the rest of your program.

A promise is in one of these states:
1. Pending: outcome not yet determined
2. Fulfilled: completed, the promise result is a value
3. Rejected: failed, result is an error

Promises can be chained together to perform a sequence of asynchronous operations one after the other. Once a Promise is fulfilled or rejected, it is considered settled and its state cannot change.

Scenario: Fetch API
One common scenario where Promises are useful is when dealing with AJAX requests in a web app. You might want to fetch data from a server, and because network operations can take a significant amount of time, you want them to be asynchronous so they don’t block the rest of your code.

We can then use then on the Promise object with a callback that takes the response object and return another promise that resolves to data we want to use or perform an operation straight away. catch to handle errors.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Can you explain how map(), reduce(), and filter() methods work in JavaScript? When would you use each?

A

A higher order function is a function that takes one or more functions as arguments, or returns a function as its result.

map(), reduce(), and filter() are higher-order functions in JavaScript that operate on arrays. Each takes a callback function as an argument and applies it in a certain way to produce a new result.

map(): creates a new array with the results of calling a provided function on every element in the calling array. It doesn’t modify the original array and returns a new array where the length matches the original assuming there are no undefined.

reduce(): applies a function against an accumulator and each element in the array from left -> right to reduce it to a single output value.

filter(): creates a new array with all the elements that pass the test/condition implemented by the provided function.

When to use each?
map(): when we want to transform all elements in an array
reduce(): when you want to compute a single value from all elements in array
filter(): when you want to select a subset of elements from an array based on a condition

They follow functional programming principles which avoids side effects, mutating data, etc.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

What is the difference between a shallow copy and a deep copy? How would you create a deep copy of an object in JavaScript?

A

A shallow copy of an object is a copy where the new object has its own copy of the primitive data types (like numbers, strings, booleans), but any object references (including arrays, other objects, functions, etc.) point to the same objects as the original.

A deep copy of an object means creating a new object who’s primitive types and object references are copied over, so changes to one object do not affect the other. This includes recursively copying all objects and arrays.

One common method to create a deep copy of an object is to use JSON.stringify() to convert the object into a string, then JSON.parse() to parse it back into a new object:

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Explain the concept of closure in JavaScript. Can you provide a practical use case?

A

A function that has access to its own scope, the outer scope and global scope. Basically, a function that is bundled with its lexical (parent) scope.

Even after outerFunction has finished executing and its execution context has been removed from the stack, innerFunction still has access to outerVariable. This is the power of closures - they keep the scope alive.

They’re particularly useful when you want to create functions on the fly with data that they should “remember”, or when you’re doing data encapsulation or object data privacy.

A practical use case for closures is data privacy or creating “private” variables. In JavaScript, we can’t have private variables due to its scoping rules, but closures give us a way to mimic them.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

What are Template Literals in ES6? Can you give an example of how they can be used to enhance string manipulation?

A

A new way to define strings in JS. They provide a concise and convenient syntax to create strings and allow us to embed expressions within strings, perform multi-line string formatting, and create tagged templates.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

What is the spread operator and how is it used in JavaScript? Can you provide an example?

A

The spread (…) operator in JS is used to unpack elements of iterable objects (like arrays or objects) into a list of elements.

Use cases:
1. Copying arrays: shallow copy of an array
2. Concatenating arrays let arr3 = [...arr1, ...arr2]
3. Using in function arguments sum(a,b,c) => sum(…[1,2,3])
4. Spreading objects: copy properties from one object to another

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

How does JavaScript handle asynchronous operations? Can you explain the event loop and how it relates to the call stack?

A

JS is single-threaded, so it executes one operation at a time in a single sequence. However, many operations like network requests are asynchronous, and can take a significant amount of time to complete. If a program waits for these operations synchronously, it would block the rest of the program from running.

To handle this, JS uses a combination of the CALL STACK, BROWSER WEB APIs, EVENT QUEUE, and the EVENT LOOP.

Call stack: a DS that tracks the program execution context to know what function is currently running and its nested calls. JS can only do one thing at a time since it has only one call stack. If a function is called, it’s added to the top of the stack. If a function is complete, it’s removed from the stack.

Web APIs and Event Queue: When an async operation like setTimeout or AJAX call is encountered. The operation is sent to be handled by the browser. Once the operation finishes (like timer expires, the network request receives a response), the provided callback function is sent to the event queue.

Event loop: this continuously checks if the call stack is empty. If yes: take the first callback function in the queue and pushes it onto the call stack to be executed.

In short: call stack handles the synchronous, line-by-line execution of code. Web APIs handle async operations. Once they are done, the callbacks enters the event queue. The event loop monitors the call stack and event queue, moving callbacks onto the stack when the stack is empty.

These all allow JS to be non-blocking and async, so it can finish other tasks without waiting for previous time consuming ones => performance and UX.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

What is the purpose of async/await introduced in ES8? How does it improve upon promises?

A

Async/Await basically provides a more concise and easier-to-understand syntax for working with Promises, which are used for asynchronous operations in JavaScript.

Promises significantly improved the way we handle asynchronous operations, helping us avoid “callback hell” and making the code more readable and maintainable. However, Promises still use callbacks (.then() and .catch()), and complex Promise chains can still lead to somewhat difficult-to-read code.

So this is where async/await comes in:

Async: When placed before a function, async ensures that the function returns a Promise. If a value is returned from the function, it will be wrapped in a resolved Promise. If nothing is returned, a Promise that resolves to undefined is returned. If an error is thrown, it will return a rejected Promise.

Await: the await operator is used only inside an async function and makes JS wait until the Promise returns a result. It essentially pauses the execution of the async function and resumes when the Promise is either resolved or rejected, and then returns the result. This allows us to write asynchronous code that appears synchronous. Making it easier to read and understand. Also easier with try/catch block syntactic sugar for error handling which isn’t possible with plain promises.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Explain what ‘hoisting’ means in JavaScript. How does this behavior differ for var, let, and const?

A

Hoisting is a JavaScript mechanism where variable and function declarations are put into memory during the compile phase. This means that no matter where functions and variables are declared, they are moved to the top of their scope regardless of whether their scope is a global or a local.

var: when you declare a variable with ‘var’, both the declaration and the definition are hoisted (but definition is hoisted as ‘undefined’.

let and const: only the declarations are hoisted to the top of the block so you will get ‘ReferenceError’ because they are in the temporal dead zone from the start of the block until the declaration is processed.

Also this is likely because of var being in global scope as well since it’s is also added to the Window/Global object.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

What are JavaScript modules in ES6? How do they differ from libraries in ‘vanilla’ JavaScript?

A

ES6 introduced the concept of JavaScript modules, which allow developers to break up their code into separate, reusable pieces, each encapsulating the code and functionality that serves a single purpose.

Modules are defined using export and imported using import. They are different from scripts because they allow you to export and import functions, objects, or values from one module to another, facilitating the reusability and maintainability of code.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Explain the Prototype Chain and Inheritance in JavaScript.

A

Every object in JavaScript has a built-in property, which is called its prototype. The prototype is itself an object, so the prototype will have its own prototype, making what’s called a prototype chain. The chain ends when we reach a prototype that has null for its own prototype.

Prototype

> It’s like a map for that object type, it contains the functionalities for that object ttype. Any object that is instantiated will point to that prototype instead of creating new property in every instance (like a singleton in some way).

In a lot of cases it’s better to use prototype properties to add methods rather than creating the method inside the class.

JavaScript uses a Prototype Inheritance Model. That means that every constructor function/class has a prototype property that is shared by every instance of the constructor/class. So any methods and properties or prototype can be accessed by every instance. Prototype property returns an object.

Every object type has a prototype, and all instances created from that object type inherit the prototype methods. Only the constructor function has the prototype property.

function User(name) {
this.name = name;
}

User.prototype.sayHi = function () {
console.log(this.name);
};

let user = new User(‘John’);
user.sayHi(); // John

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Differences between == and === operators.

A

Triple Equals (===)
- Returns true if both operands are of the same type and contain the same value.
- Does not perform type conversion.
- Preferred operator for equality comparison in JavaScript.
- Use it when you want to compare values strictly, considering both value and type.

Double Equals (==)
- Tries to perform type conversion if the types of the operands differ and then compares for equality.
- Performs complex type conversions, which can lead to unexpected results.
- Not recommended for equality comparison in JavaScript.
- Use it cautiously and with awareness of the type conversion rules.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

JavaScript Event Model: Event Propagation, Event Bubbling and Event Capturing.

A

Event Propagation is the flow of the event in the DOM. It describes the order in which elements receive the event. It includes two phases: Capturing and Bubbling.

Event Capturing (or Trickling): In the capturing phase, the event starts from the top element (document object), and then it propagates down to the target element’s parents until it reaches the target element. It’s like the event is captured at the highest level and then trickled down to the element where the event occurred.

Event Bubbling: In the bubbling phase, the event starts from the target element, and then it bubbles up to the topmost parent (document object). It’s like a bubble in water, which starts at the bottom and then rises up to the surface.

Let’s say if we have two buttons: parent and child button, child button is inside parent button. If we click child button, we also clicked parent button.

The click event first gets dispatched to the child, then bubbles up to the parent. This is Event Bubbling.

Stopping Propagation: You can stop the event from propagating further either in capturing or bubbling phase using the stopPropagation() method. This can be useful when you don’t want parent handlers to be triggered.

Event Delegation: Understanding event propagation is key to event delegation, a technique where you delegate the handling of events for child elements to a single parent element. This can significantly improve performance for large amounts of elements.

18
Q

Concepts of Callbacks and Promises in Asynchronous JavaScript.

A

A callback is a function that is to be executed after another function has finished executing, hence the name ‘callback’. In JavaScript, functions are objects and can be passed as arguments to other functions and can be executed after some event. However, managing asynchronous operations with callbacks can become more complex as you start to handle more tasks. This situation is sometimes referred to as “callback hell”.

To avoid “callback hell”, ES6 introduced Promises. A Promise is an object representing the eventual completion or failure of an asynchronous operation. It returns a value which is either a resolved value or a reason why it’s rejected.

19
Q

Cross-browser compatibility issues and how to handle them.

A

Common issues include differences in:
- HTML and CSS interpretation and rendering
- JavaScript execution
- Unsupported features or APIs
- Layout and design inconsistencies

Solutions:
- Feature Detection
- Graceful degradation
- Progressive enhancement
- CSS Resets
- Cross-browser compatible libraries

20
Q

Concepts around the Document Object Model (DOM) and manipulating it.

A

The Document Object Model (DOM) is a programming interface for HTML and XML documents. It represents the structure of a document as a tree of objects, allowing scripts to access and manipulate the content and structure of a web page.

  1. Nodes
    In the DOM, all parts of the document, such as elements, attributes, and text, are represented by nodes. There are several types of nodes, but the most common are element nodes and text nodes.
  2. Element, Attribute, and Text Nodes
    An element node represents an HTML element in the document, an attribute node represents an attribute of an element, and a text node represents the text content of an element.
  3. The Document Object
    The document object is an entry point into the web page’s content. It’s a part of the Window object and can be used to access and manipulate the HTML content.
21
Q

What is functional programming?

A

A programming paradigm where programs are constructed by applying and composing functions. It’s a declarative programming style that focuses on what to solve rather than how to solve. Its primary focus of what to solve in terms of function compositions and applications, instead of changing state and mutable data.

It involves:
1. Immutable data: data never changes, whenever we want to modify a data structure and its content => create a new copy and do so
2. Pure functions: takes in input and return an output without modifying any data outside its scope. Inherently testable and reliable since it doesn’t rely on external state.
3. First-class and Higher order functions: functions can be stored in variables, passed as function arguments and returned as results.
4. Function composition: Combining functions to produce new function or perform operation.
5. Avoid side effects: discourages changes in state and mutable data.

22
Q

What is the difference between classical inheritance and prototypal inheritance?

A

Class Inheritance: instances inherit from classes (like a blueprint — a description of the class), and create sub-class relationships: hierarchical class taxonomies. Instances are typically instantiated via constructor functions with the new keyword. Class inheritance may or may not use the class keyword from ES6.

Prototypal Inheritance: instances inherit directly from other objects. Instances are typically instantiated via factory functions or Object.create(). Instances may be composed from many different objects, allowing for easy selective inheritance.

Prototypal is much more simpler and flexible

23
Q

Can you provide an example of how to use the Set and Map classes in JavaScript? What are their advantages over traditional arrays and objects?

A

The Set and Map objects are collections which store unique elements.

Set is a collection of unique values without keys. Basically a glorified array that filters out duplicates on every insertion and specializes with unique values. Can be iterated with for..of or forEach

Map is a collection of keyed data items, just like an Object but the main difference is that Map allows keys of any type. In Object; can’t use object as keys for other objects and it converts object keys into a string.

24
Q

How does async/await make handling Promises easier? Can you provide an example?

A

async/await makes handling Promises easier by providing a synchronous-looking way to write asynchronous code. They are a syntactic sugar on top of Promises.

25
Q

If you use map on an array in JavaScript, does it change the size of the array? Why or why not?

A

Using map on an array does not change the size of the original array. It creates a new array with the results of calling a provided function on every element in the array. The size of the new array will be the same as the original array, unless undefined values are returned.

26
Q

Can you explain how you’d use Promise methods (Promise.all, Promise.race, etc.) to manage multiple asynchronous operations?

A

Promise methods like Promise.all and Promise.race allow us to handle multiple promises simultaneously. Promise.all waits for all promises to resolve, and then resolves itself with an array of the results, in the same order as the original promises. Promise.race resolves as soon as any of the promises resolve, and it resolves with the value of the first resolved promise.

27
Q

What would happen if you created a Promise chain with an array? What would it resolve to?

A

If you create a Promise chain with an array, it would resolve to the last value in the chain, or the catch error value if a promise gets rejected.

28
Q

If a console.log statement is placed inside a setTimeout with a delay of 0, when would it be printed to the console?

A

setTimeout with a delay of 0 doesn’t execute the callback function immediately. It adds the callback function to the queue of tasks to be executed. The tasks in this queue are executed when the stack is empty and all other higher-priority tasks are finished. It’s placed on the event queue and waits for the call stack to clear before it’s executed.

29
Q

How would you handle sending 1000 HTTP requests as quickly as possible from a single client to a single backend in JavaScript? What kind of challenges might you encounter and how would you overcome them?

A

You could handle sending 1000 HTTP requests from a single client to a single backend using Promise.all to send multiple requests concurrently. Challenges you might encounter include API rate limits, network issues, and handling failed requests. To overcome these, you can add retry logic, handle each request error individually, and potentially add delays or backoff if you’re hitting rate limits.

30
Q

What are JavaScript generators and how are they different from regular functions?

A

JavaScript generators are special types of functions that can be paused and resumed, which allows other code to run during these pause periods. This makes generators great for dealing with asynchronous operations. They’re declared with function* and yield to pause.

Some use cases:
- for loops which need to be paused and resumed at a later date
- infinitely looping over an array and having it reset to the beginning once it’s done
- creating iterables to use in for of loops from non-iterable objects using [Symbol.Iterator]

31
Q

What is a JavaScript Proxy and what is it used for?

A

A Proxy in JavaScript is a powerful object that is used to intercept and define custom behavior for fundamental operations (e.g., property lookup, assignment, enumeration, function invocation, etc).

32
Q

Explain how import and export work in ES6 modules.

A

In ES6, import and export statements allow us to split our code into multiple, reusable modules.

33
Q

What are the drawbacks of using arrow functions?

A

Arrow functions have a few limitations:

  • They don’t have their own this value. They inherit it from the enclosing scope, which can cause unexpected behavior in object methods or event handlers.
  • They can’t be used as constructors.
  • They don’t have the arguments object.
  • They’re anonymous, which can make debugging harder.
34
Q

Explain the concept of a JavaScript Symbol.

A

A Symbol is a unique and immutable data type introduced in ES6. It is often used as an identifier for object properties because a symbol never conflicts with any other property key (string or symbol).

35
Q

What is BigInt and why would you use it?

A

BigInt is a built-in object that provides a way to represent whole numbers larger than 2^53 - 1, which is the largest number JavaScript can reliably handle with the Number primitive.

36
Q

What is a service worker and what are some of its benefits?

A

Service Workers are a type of web worker. They act as a proxy server that sits between web applications, and the browser and network (when available). They are designed to (amongst other things) enable the creation of effective offline experiences, and intercept network requests and take appropriate action based on whether the network is available and updated assets reside on the server.

37
Q

How do you handle data immutability in JavaScript?

A
  1. Using the const keyword to declare variables that cannot be reassigned.
  2. Using methods that return new copies of the original data with the changes, such as .map(), .filter(), and .reduce() for arrays.
  3. Using libraries that enforce immutability, such as Immutable.js or Mori.
  4. Using the spread operator … to create copies of objects or arrays.
38
Q

What are the security risks associated with JavaScript and how can you mitigate them?

A
  • Cross-Site Scripting (XSS): Mitigated by validating and escaping user inputs, and using Content Security Policy (CSP).
  • Cross-Site Request Forgery (CSRF): Mitigated by using anti-CSRF tokens and enforcing SameSite Cookies.
  • Code Injection: Again, validate and escape user inputs, and never use eval().
  • Security issues related to third-party scripts or libraries: Keep libraries up to date, and review the security practices of third-party scripts.
  • Potential exposure of sensitive data: Ensure data is encrypted, never store sensitive data in plain text or in local storage.
39
Q

Explain WeakSet and WeakMap

A

WeakMap is basically a Map where the keys must strictly be objects and keys will only stay in the Map if and only if the key has a value pair. Otherwise it will automatically be garbage collected from the memory. It only supports the basic Map methods and doesn’t support iteration so there’s no way to get all the values from it.
Used for: storing temporary additional data, caching

WeakSet is like a Set like collection that only stores Objects and removes them once they become inaccessible by other means. Weak reference to object so can easily be removed by garbage collector (doesn’t store primitive and no iteration). This comes at the cost of not having support for Set methods like clear, size, keys, values.
Used for: keeping track of unique site visitors

Both are used mainly for secondary storage purposes in addition to primary objects.

40
Q

Explain difference between undefined and null

A

while both are similar where it signifies there’s no value, it works with type coercion when doing falsy equality comparisons

null is an object that represents nothing, void, emptiness, a value that is intentionally set.
undefined however is a data type that is like a container with a missing value, often times expecting something but there might be a mistake somewhere in the code that returns undefined, like a invoking a function with no return

41
Q

Map vs Object

A

Collection of data items with key pair value like object. Map allows keys of any types.
Map has a bunch of methods for key-pair operations and they store only unique key items and keys are not converted into strings like Objects. Maps are also iterable as it comes with built in looping methods and insertion order is used.