Tech Interview

Asymptotic Notation

Definition:

Asymptotic Notation is the hardware independent notation used to tell the time and space complexity of an algorithm. Meaning it’s a standardized way of measuring how much memory an algorithm uses or how long it runs for given an input.

Complexities

The following are the Asymptotic rates of growth from best to worst:

Big-O notation

Big-O refers to the upper bound of time or space complexity of an algorithm, meaning it worst case runtime scenario. An easy way to think of it is that runtime could be better than Big-O but it will never be worse.

Big-Ω (Big-Omega) notation

Big-Omega refers to the lower bound of time or space complexity of an algorithm, meaning it is the best runtime scenario. Or runtime could worse than Big-Omega, but it will never be better.

Big-θ (Big-Theta) notation

Big-Theta refers to the tight bound of time or space complexity of an algorithm. Another way to think of it is the intersection of Big-O and Big-Omega, or more simply runtime is guaranteed to be a given complexity, such as n log n.

What you need to know

Data Structures

Array

Definition

What you need to know

Time Complexity

Linked List

Definition

What you need to know

Time Complexity

Hash Table or Hash Map

Definition

What you need to know

Time Complexity

Binary Tree

Definition

What you need to know

Time Complexity

Algorithms

Algorithm Basics

Recursive Algorithms

Definition

What you need to know

Iterative Algorithms

Definition

What you need to know

Recursion Vs. Iteration

Pseudo Code of Moving Through an Array

| Recursion                    | Iteration                     |
| ---------------------------- | ----------------------------- |
| recursive method (array, n)  | iterative method (array)      |
| if array[n] is not nil       | for n from 0 to size of array |
| print array[n]               | print(array[n])               |
| recursive method(array, n+1) |
| else                         |
| exit loop                    |

Greedy Algorithms

Definition

What you need to know

Pseudo Code of a Greedy Algorithm to Find Largest Difference of any Two Numbers in an Array.

greedy algorithm (array)
  let largest difference = 0
  let new difference = find next difference (array[n], array[n+1])
  largest difference = new difference if new difference is > largest difference
  repeat above two steps until all differences have been found
  return largest difference

This algorithm never needed to compare all the differences to one another, saving it an entire iteration.

Search Algorithms

Definition

What you need to know

Time Complexity

Definition

What you need to know

Time Complexity

Nuances

Sorting Algorithms

Selection Sort

Definition

What you need to know

Time Complexity

Space Complexity

Visualization

# (source: Wikipedia, Insertion Sort)

Insertion Sort

Definition

What you need to know

Time Complexity

Space Complexity

Visualization

# (source: Wikipedia, Insertion Sort)

Merge Sort

Definition

What you need to know

Time Complexity

Space Complexity

Visualization

# (source: Wikipedia, Merge Sort)

Quicksort

Definition

What you need to know

Time Complexity

Space Complexity

Visualization

# (source: Wikipedia, Quicksort)

Merge Sort Vs. Quicksort

Additional Resources

Khan Academy’s Algorithm Course

What is ARIA and when should you use it?

Answer

ARIA stands for “Accessible Rich Internet Applications”, and is a technical specification created by the World Wide Web Consortium (W3C). Better known as WAI-ARIA, it provides additional HTML attributes in the development of web applications to offer people who use assistive technologies (AT) a more robust and interoperable experience with dynamic components. By providing the component’s role, name, and state, AT users can better understand how to interact with the component. WAI-ARIA should only be used when an HTML element equivalent is not available or lacks full browser or AT support. WAI-ARIA’s semantic markup coupled with JavaScript works to provide an understandable and interactive experience for people who use AT. An example using ARIA:

Credit: W3C’s ARIA 1.1 Combobox with Grid Popup Example

Don’t forget:

Answer

4.5:1 is the calculated contrast ratio between foreground text and background that is recommended by the Web Content Accessibiity Guidelines (WCAG) success criteria (SC) 1.4.3: Contrast (Minimum). This SC was written by the World Wide Web Consortium (W3C) to ensure that people with low vision or color deficiencies are able to read (perceive) important content on a web page. It goes beyond color choices to ensure text stands out on the background it’s placed on.

Don’t forget:

What are some of the tools available to test the accessibility of a website or web application?

Answer

There are multiple tools that can help you to find for accessibility issues in your website or application. Check for issues in your website:

Don’t forget:

What is the Accessibility Tree?

Answer

The Accessibility Tree is a structure produced by the browser’s Accessibility APIs which provides accessibility information to assistive technologies such as screen readers. It runs parallel to the DOM and is similar to the DOM API, but with much fewer nodes, because a lot of that information is only useful for visual presentation. By writing semantic HTML we can take advantage of this process in creating an accessible experience for our users.

Don’t forget:

What is the purpose of the alt attribute on images?

Answer

The alt attribute provides alternative information for an image if a user cannot view it. The alt attribute should be used to describe any images except those which only serve a decorative purpose, in which case it should be left empty.

Don’t forget:

What are defer and async attributes on a <script> tag?

Answer

If neither attribute is present, the script is downloaded and executed synchronously, and will halt parsing of the document until it has finished executing (default behavior). Scripts are downloaded and executed in the order they are encountered. The defer attribute downloads the script while the document is still parsing but waits until the document has finished parsing before executing it, equivalent to executing inside a DOMContentLoaded event listener. defer scripts will execute in order. The async attribute downloads the script during parsing the document but will pause the parser to execute the script before it has fully finished parsing. async scripts will not necessarily execute in order. Note: both attributes must only be used if the script has a src attribute (i.e. not an inline script).

<script src="myscript.js"></script>
<script src="myscript.js" defer></script>
<script src="myscript.js" async></script>

Don’t forget:

What is an async function?

async function foo() {
  ...
}

Answer

An async function is a function that allows you to pause the function’s execution while it waits for (awaits) a promise to resolve. It’s an abstraction on top of the Promise API that makes asynchronous operations look like they’re synchronous. async functions automatically return a Promise object. Whatever you return from the async function will be the promise’s resolution. If instead you throw from the body of an async function, that will be how your async function rejects the promise it returns. Most importantly, async functions are able to use the await keyword in their function body, which pauses the function until the operation after the await completes, and allows it to return that operation’s result to a variable synchronously.

// Normal promises in regular function:
function foo() {
  promiseCall().then((result) => {
    // do something with the result
  });
}
// async functions
async function foo() {
  const result = await promiseCall();
  // do something with the result
}

Don’t forget:

Create a function batches that returns the maximum number of whole batches that can be cooked from a recipe.

/**
It accepts two objects as arguments: the first object is the recipe
for the food, while the second object is the available ingredients.
Each ingredient's value is a number representing how many units there are.
`batches(recipe, available)`
*/
// 0 batches can be made
batches(
  { milk: 100, butter: 50, flour: 5 },
  { milk: 132, butter: 48, flour: 51 }
);
batches(
  { milk: 100, flour: 4, sugar: 10, butter: 5 },
  { milk: 1288, flour: 9, sugar: 95 }
);
// 1 batch can be made
batches(
  { milk: 100, butter: 50, cheese: 10 },
  { milk: 198, butter: 52, cheese: 10 }
);
// 2 batches can be made
batches(
  { milk: 2, sugar: 40, butter: 20 },
  { milk: 5, sugar: 120, butter: 500 }
);

Answer

We must have all ingredients of the recipe available, and in quantities that are more than or equal to the number of units required. If just one of the ingredients is not available or lower than needed, we cannot make a single batch. Use Object.keys() to return the ingredients of the recipe as an array, then use Array.prototype.map() to map each ingredient to the ratio of available units to the amount required by the recipe. If one of the ingredients required by the recipe is not available at all, the ratio will evaluate to NaN, so the logical OR operator can be used to fallback to 0 in this case. Use the spread ... operator to feed the array of all the ingredient ratios into Math.min() to determine the lowest ratio. Passing this entire result into Math.floor() rounds down to return the maximum number of whole batches.

const batches = (recipe, available) =>
  Math.floor(
    Math.min(...Object.keys(recipe).map((k) => available[k] / recipe[k] || 0))
  );

Don’t forget:

What is CSS BEM?

Answer

The BEM methodology is a naming convention for CSS classes in order to keep CSS more maintainable by defining namespaces to solve scoping issues. BEM stands for Block Element Modifier which is an explanation for its structure. A Block is a standalone component that is reusable across projects and acts as a “namespace” for sub components (Elements). Modifiers are used as flags when a Block or Element is in a certain state or is different in structure or style.

/* block component */
.block {
}
/* element */
.block__element {
}
/* modifier */
.block__element--modifier {
}

Here is an example with the class names on markup:

<nav class="navbar">
  <a href="/" class="navbar__link navbar__link--active"></a>
  <a href="/" class="navbar__link"></a>
  <a href="/" class="navbar__link"></a>
</nav>

In this case, navbar is the Block, navbar__link is an Element that makes no sense outside of the navbar component, and navbar__link--active is a Modifier that indicates a different state for the navbar__link Element. Since Modifiers are verbose, many opt to use is-* flags instead as modifiers.

<a href="/" class="navbar__link is-active"></a>

These must be chained to the Element and never alone however, or there will be scope issues.

.navbar__link.is-active {
}

Don’t forget:

What is Big O Notation?

Answer

Big O notation is used in Computer Science to describe the time complexity of an algorithm. The best algorithms will execute the fastest and have the simplest complexity. Algorithms don’t always perform the same and may vary based on the data they are supplied. While in some cases they will execute quickly, in other cases they will execute slowly, even with the same number of elements to deal with. In these examples, the base time is 1 element = 1ms.

O(1)

arr[arr.length - 1];

O(N)

arr.filter(fn);

O([1, N])

arr.some(fn);

O(NlogN)

arr.sort(fn);

O(N^2)

for (let i = 0; i < arr.length; i++) {
  for (let j = 0; j < arr.length; j++) {
    // ...
  }
}

O(N!)

const permutations = (arr) => {
  if (arr.length <= 2) return arr.length === 2 ? [arr, [arr[1], arr[0]]] : arr;
  return arr.reduce(
    (acc, item, i) =>
      acc.concat(
        permutations([...arr.slice(0, i), ...arr.slice(i + 1)]).map((val) => [
          item,
          ...val,
        ])
      ),
    []
  );
};

Don’t forget:

Create a standalone function bind that is functionally equivalent to the method Function.prototype.bind.

function example() {
  console.log(this);
}
const boundExample = bind(example, { a: true });
boundExample.call({ b: true }); // logs { a: true }

Answer

Return a function that accepts an arbitrary number of arguments by gathering them with the rest ... operator. From that function, return the result of calling the fn with Function.prototype.apply to apply the context and the array of arguments to the function.

const bind =
  (fn, context) =>
  (...args) =>
    fn.apply(context, args);

Don’t forget:

What is the purpose of cache busting and how can you achieve it?

Answer

Browsers have a cache to temporarily store files on websites so they don’t need to be re-downloaded again when switching between pages or reloading the same page. The server is set up to send headers that tell the browser to store the file for a given amount of time. This greatly increases website speed and preserves bandwidth. However, it can cause problems when the website has been changed by developers because the user’s cache still references old files. This can either leave them with old functionality or break a website if the cached CSS and JavaScript files are referencing elements that no longer exist, have moved or have been renamed. Cache busting is the process of forcing the browser to download the new files. This is done by naming the file something different to the old file. A common technique to force the browser to re-download the file is to append a query string to the end of the file.

Don’t forget:

How can you avoid callback hells?

getData(function (a) {
  getMoreData(a, function (b) {
    getMoreData(b, function (c) {
      getMoreData(c, function (d) {
        getMoreData(d, function (e) {
          // ...
        });
      });
    });
  });
});

Answer

Refactoring the functions to return promises and using async/await is usually the best option. Instead of supplying the functions with callbacks that cause deep nesting, they return a promise that can be awaited and will be resolved once the data has arrived, allowing the next line of code to be evaluated in a sync-like fashion. The above code can be restructured like so:

async function asyncAwaitVersion() {
  const a = await getData();
  const b = await getMoreData(a);
  const c = await getMoreData(b);
  const d = await getMoreData(c);
  const e = await getMoreData(d);
  // ...
}

There are lots of ways to solve the issue of callback hells:

Don’t forget:

What is the purpose of callback function as an argument of setState?

Answer

The callback function is invoked when setState has finished and the component gets rendered. Since setState is asynchronous, the callback function is used for any post action.

setState({ name: "sudheer" }, () => {
  console.log("The name has updated and component re-rendered");
});

Don’t forget:

Which is the preferred option between callback refs and findDOMNode()?

Answer

Callback refs are preferred over the findDOMNode() API, due to the fact that findDOMNode() prevents certain improvements in React in the future.

// Legacy approach using findDOMNode()
class MyComponent extends Component {
  componentDidMount() {
    findDOMNode(this).scrollIntoView();
  }
  render() {
    return <div />;
  }
}
// Recommended approach using callback refs
class MyComponent extends Component {
  componentDidMount() {
    this.node.scrollIntoView();
  }
  render() {
    return <div ref={(node) => (this.node = node)} />;
  }
}

Don’t forget:

What is a callback? Can you show an example using one?

Answer

Callbacks are functions passed as an argument to another function to be executed once an event has occurred or a certain task is complete, often used in asynchronous code. Callback functions are invoked later by a piece of code but can be declared on initialization without being invoked. As an example, event listeners are asynchronous callbacks that are only executed when a specific event occurs.

function onClick() {
  console.log("The user clicked on the page.");
}
document.addEventListener("click", onClick);

However, callbacks can also be synchronous. The following map function takes a callback function that is invoked synchronously for each iteration of the loop (array element).

const map = (arr, callback) => {
  const result = [];
  for (let i = 0; i < arr.length; i++) {
    result.push(callback(arr[i], i));
  }
  return result;
};
map([1, 2, 3, 4, 5], (n) => n * 2); // [2, 4, 6, 8, 10]

Don’t forget:

What is the children prop?

Answer

children is part of the props object passed to components that allows components to be passed as data to other components, providing the ability to compose components cleanly. There are a number of methods available in the React API to work with this prop, such as React.Children.map, React.Children.forEach, React.Children.count, React.Children.only and React.Children.toArray. A simple usage example of the children prop is as follows:

function GenericBox({ children }) {
  return <div className="container">{children}</div>;
}
function App() {
  return (
    <GenericBox>
      <span>Hello</span> <span>World</span>
    </GenericBox>
  );
}

Don’t forget:

Why does React use className instead of class like in HTML?

Answer

React’s philosophy in the beginning was to align with the browser DOM API rather than HTML, since that more closely represents how elements are created. Setting a class on an element meant using the className API:

const element = document.createElement("div");
element.className = "hello";

Additionally, before ES5, reserved words could not be used in objects:

const element = {
  attributes: {
    class: "hello",
  },
};

In IE8, this will throw an error. In modern environments, destructuring will throw an error if trying to assign to a variable:

const { class } = this.props // Error
const { className } = this.props // All good
const { class: className } =
    this.props // All good, but
        cumbersome!

However, class can be used as a prop without problems, as seen in other libraries like Preact. React currently allows you to use class, but will throw a warning and convert it to className under the hood. There is currently an open thread (as of January 2019) discussing changing className to class to reduce confusion.

Don’t forget:

How do you clone an object in JavaScript?

Answer

Using the object spread operator ..., the object’s own enumerable properties can be copied into the new object. This creates a shallow clone of the object.

const obj = { a: 1, b: 2 };
const shallowClone = { ...obj };

With this technique, prototypes are ignored. In addition, nested objects are not cloned, but rather their references get copied, so nested objects still refer to the same objects as the original. Deep-cloning is much more complex in order to effectively clone any type of object (Date, RegExp, Function, Set, etc) that may be nested within the object. Other alternatives include:

Don’t forget:

What is a closure? Can you give a useful example of one?

Answer

A closure is a function defined inside another function and has access to its lexical scope even when it is executing outside its lexical scope. The closure has access to variables in three scopes:

Don’t forget:

How do you compare two objects in JavaScript?

Answer

Even though two different objects can have the same properties with equal values, they are not considered equal when compared using == or ===. This is because they are being compared by their reference (location in memory), unlike primitive values which are compared by value. In order to test if two objects are equal in structure, a helper function is required. It will iterate through the own properties of each object to test if they have the same values, including nested objects. Optionally, the prototypes of the objects may also be tested for equivalence by passing true as the 3rd argument. Note: this technique does not attempt to test equivalence of data structures other than plain objects, arrays, functions, dates and primitive values.

function isDeepEqual(obj1, obj2, testPrototypes = false) {
  if (obj1 === obj2) {
    return true;
  }
  if (typeof obj1 === "function" && typeof obj2 === "function") {
    return obj1.toString() === obj2.toString();
  }
  if (obj1 instanceof Date && obj2 instanceof Date) {
    return obj1.getTime() === obj2.getTime();
  }
  if (
    Object.prototype.toString.call(obj1) !==
      Object.prototype.toString.call(obj2) ||
    typeof obj1 !== "object"
  ) {
    return false;
  }
  const prototypesAreEqual = testPrototypes
    ? isDeepEqual(
        Object.getPrototypeOf(obj1),
        Object.getPrototypeOf(obj2),
        true
      )
    : true;
  const obj1Props = Object.getOwnPropertyNames(obj1);
  const obj2Props = Object.getOwnPropertyNames(obj2);
  return (
    obj1Props.length === obj2Props.length &&
    prototypesAreEqual &&
    obj1Props.every((prop) => isDeepEqual(obj1[prop], obj2[prop]))
  );
}

Don’t forget:

What is context?

Answer

Context provides a way to pass data through the component tree without having to pass props down manually at every level. For example, authenticated user, locale preference, UI theme need to be accessed in the application by many components.

const { Provider, Consumer } = React.createContext(defaultValue);

Don’t forget:

What is CORS?

Answer

Cross-Origin Resource Sharing or CORS is a mechanism that uses additional HTTP headers to grant a browser permission to access resources from a server at an origin different from the website origin. An example of a cross-origin request is a web application served from http://mydomain.com that uses AJAX to make a request for http://yourdomain.com. For security reasons, browsers restrict cross-origin HTTP requests initiated by JavaScript. XMLHttpRequest and fetch follow the same-origin policy, meaning a web application using those APIs can only request HTTP resources from the same origin the application was accessed, unless the response from the other origin includes the correct CORS headers.

Don’t forget:

Describe the layout of the CSS Box Model and briefly describe each component.

Answer

Content: The inner-most part of the box filled with content, such as text, an image, or video player. It has the dimensions content-box width and content-box height. Padding: The transparent area surrounding the content. It has dimensions padding-box width and padding-box height. Border: The area surrounding the padding (if any) and content. It has dimensions border-box width and border-box height. Margin: The transparent outer-most layer that surrounds the border. It separates the element from other elements in the DOM. It has dimensions margin-box width and margin-box height. alt text alt text

Don’t forget:

What are the advantages of using CSS preprocessors?

Answer

CSS preprocessors add useful functionality that native CSS does not have, and generally make CSS neater and more maintainable by enabling DRY (Don’t Repeat Yourself) principles. Their terse syntax for nested selectors cuts down on repeated code. They provide variables for consistent theming (however, CSS variables have largely replaced this functionality) and additional tools like color functions (lighten, darken, transparentize, etc), mixins, and loops that make CSS more like a real programming language and gives the developer more power to generate complex CSS.

Don’t forget:

What is the difference between ‘+’ and ‘~’ sibling selectors?.

Answer

The General Sibling Selector ~ selects all elements that are siblings of a specified element. The following example selects all <p> elements that are siblings of <div> elements:

div ~ p {
  background-color: blue;
}

The Adjacent Sibling Selector + selects all elements that are the adjacent siblings of a specified element. The following example will select all <p> elements that are placed immediately after <div> elements:

div + p {
  background-color: red;
}

Don’t forget:

Can you describe how CSS specificity works?

Answer

Assuming the browser has already determined the set of rules for an element, each rule is assigned a matrix of values, which correspond to the following from highest to lowest specificity:

Don’t forget:

What is debouncing?

Answer

Debouncing is a process to add some delay before executing a function. It is commonly used with DOM event listeners to improve the performance of page. It is a technique which allow us to “group” multiple sequential calls in a single one. A raw DOM event listeners can easily trigger 20+ events per second. A debounced function will only be called once the delay has passed.

const debounce = (func, delay) => {
  let debounceTimer;
  return function () {
    const context = this;
    const args = arguments;
    clearTimeout(debounceTimer);
    debounceTimer = setTimeout(() => func.apply(context, args), delay);
  };
};
window.addEventListere(
  "scroll",
  debounce(function () {
    // Do stuff, this function will be called after a delay of 1 second
  }, 1000)
);

Don’t forget:

What is the DOM?

Answer

The DOM (Document Object Model) is a cross-platform API that treats HTML and XML documents as a tree structure consisting of nodes. These nodes (such as elements and text nodes) are objects that can be programmatically manipulated and any visible changes made to them are reflected live in the document. In a browser, this API is available to JavaScript where DOM nodes can be manipulated to change their styles, contents, placement in the document, or interacted with through event listeners.

Don’t forget:

What is the difference between the equality operators == and ===?

Answer

Triple equals (===) checks for strict equality, which means both the type and value must be the same. Double equals (==) on the other hand first performs type coercion so that both operands are of the same type and then applies strict comparison.

Don’t forget:

What is the difference between an element and a component in React?

Answer

An element is a plain JavaScript object that represents a DOM node or component. Elements are pure and never mutated, and are cheap to create. A component is a function or class. Components can have state and take props as input and return an element tree as output (although they can represent generic containers or wrappers and don’t necessarily have to emit DOM). Components can initiate side effects in lifecycle methods (e.g. AJAX requests, DOM mutations, interfacing with 3rd party libraries) and may be expensive to create.

const Component = () => "Hello";
const componentElement = <Component />;
const domNodeElement = <div />;

Don’t forget:

What is the difference between em and rem units?

Answer

Both em and rem units are based on the font-size CSS property. The only difference is where they inherit their values from.

Don’t forget:

What are error boundaries in React?

Answer

Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed. Class components become error boundaries if they define either (or both) of the lifecycle methods static getDerivedStateFromError() or componentDidCatch().

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }
  // Use componentDidCatch to log the error
  componentDidCatch(error, info) {
    // You can also log the error to an error reporting service
    logErrorToMyService(error, info);
  }
  // use getDerivedStateFromError to update state
  static getDerivedStateFromError(error) {
    // Display fallback UI
    return { hasError: true };
  }
  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>;
    }
    return this.props.children;
  }
}

Don’t forget:

https://reactjs.org/docs/error-boundaries.html

What is event delegation and why is it useful? Can you show an example of how to use it?

Answer

Event delegation is a technique of delegating events to a single common ancestor. Due to event bubbling, events “bubble” up the DOM tree by executing any handlers progressively on each ancestor element up to the root that may be listening to it. DOM events provide useful information about the element that initiated the event via Event.target. This allows the parent element to handle behavior as though the target element was listening to the event, rather than all children of the parent or the parent itself. This provides two main benefits:

document.querySelectorAll("button").forEach((button) => {
  button.addEventListener("click", handleButtonClick);
});

Event delegation involves using a condition to ensure the child target matches our desired element:

document.addEventListener("click", (e) => {
  if (e.target.closest("button")) {
    handleButtonClick();
  }
});

Don’t forget:

What is event-driven programming?

Answer

Event-driven programming is a paradigm that involves building applications that send and receive events. When the program emits events, the program responds by running any callback functions that are registered to that event and context, passing in associated data to the function. With this pattern, events can be emitted into the wild without throwing errors even if no functions are subscribed to it. A common example of this is the pattern of elements listening to DOM events such as click and mouseenter, where a callback function is run when the event occurs.

document.addEventListener("click", function (event) {
  // This callback function is run when the user
  // clicks on the document.
});

Without the context of the DOM, the pattern may look like this:

const hub = createEventHub();
hub.on("message", function (data) {
  console.log(`${data.username} said ${data.text}`);
});
hub.emit("message", {
  username: "John",
  text: "Hello?",
});

With this implementation, on is the way to subscribe to an event, while emit is the way to publish the event.

Don’t forget:

What is the difference between an expression and a statement in JavaScript?

Answer

There are two main syntactic categories in JavaScript: expressions and statements. A third one is both together, referred to as an expression statement. They are roughly summarized as:

Statements

let x = 0;
function declaration() {}
if (true) {
}

Statements appear as instructions that do something but don’t produce values.

// Assign `x` to the absolute value of `y`.
var x;
if (y >= 0) {
  x = y;
} else {
  x = -y;
}

The only expression in the above code is y >= 0 which produces a value, either true or false. A value is not produced by other parts of the code.

Expressions

Expressions produce a value. They can be passed around to functions because the interpreter replaces them with the value they resolve to.

5 + 5; // => 10
lastCharacter("input"); // => "t"
true === true; // => true

Expression statements

There is an equivalent version of the set of statements used before as an expression using the conditional operator:

// Assign `x` as the absolute value of `y`.
var x = y >= 0 ? y : -y;

This is both an expression and a statement, because we are declaring a variable x (statement) as an evaluation (expression).

Don’t forget:

What are truthy and falsy values in JavaScript?

Answer

A value is either truthy or falsy depending on how it is evaluated in a Boolean context. Falsy means false-like and truthy means true-like. Essentially, they are values that are coerced to true or false when performing certain operations. There are 6 falsy values in JavaScript. They are:

Boolean(""); // false
Boolean([]); // true

There is a shortcut for this using the logical NOT ! operator. Using ! once will convert a value to its inverse boolean equivalent (i.e. not false is true), and ! once more will convert back, thus effectively converting the value to a boolean.

!!""; // false
!![]; // true

Don’t forget:

Generate an array, containing the Fibonacci sequence, up until the nth term.

Answer

Initialize an empty array of length n. Use Array.prototype.reduce() to add values into the array, using the sum of the last two values, except for the first two.

const fibonacci = (n) =>
  [...Array(n)].reduce(
    (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i),
    []
  );

Don’t forget:

Given an array of words, write a method to output matching sets of anagrams.

const words = [
  "rates",
  "rat",
  "stare",
  "taser",
  "tears",
  "art",
  "tabs",
  "tar",
  "bats",
  "state",
];

Answer

const words = [
  "rates",
  "rat",
  "stare",
  "taser",
  "tears",
  "art",
  "tabs",
  "tar",
  "bats",
  "state",
];
function anagramGroups(wordAry) {
  const groupedWords = {};
  // iterate over each word in the array
  wordAry.map((word) => {
    // alphabetize the word and a separate variable
    alphaWord = word.split("").sort().join("");
    // if the alphabetize word is already a key, push the actual word value (this is an anagram)
    if (groupedWords[alphaWord]) {
      return groupedWords[alphaWord].push(word);
    }
    // otherwise add the alphabetize word key and actual word value (may not turn out to be an anagram)
    groupedWords[alphaWord] = [word];
  });
  return groupedWords;
}
// call the function and store results in a variable called collectedAnagrams
const collectedAnagrams = anagramGroups(words);
// iterate over groupedAnagrams, printing out group of values
for (const sortedWord in collectedAnagrams) {
  if (collectedAnagrams[sortedWord].length > 1) {
    console.log(collectedAnagrams[sortedWord].toString());
  }
}

Don’t forget:

Using flexbox, create a 3-column layout where each column takes up a col-{n} / 12 ratio of the container.

<div class="row">
  <div class="col-2"></div>
  <div class="col-7"></div>
  <div class="col-3"></div>
</div>

Answer

Set the .row parent to display: flex; and use the flex shorthand property to give the column classes a flex-grow value that corresponds to its ratio value.

.row {
  display: flex;
}
.col-2 {
  flex: 2;
}
.col-7 {
  flex: 7;
}
.col-3 {
  flex: 3;
}

Don’t forget:

What does 0.1 + 0.2 === 0.3 evaluate to?

Answer

It evaluates to false because JavaScript uses the IEEE 754 standard for Math and it makes use of 64-bit floating numbers. This causes precision errors when doing decimal calculations, in short, due to computers working in Base 2 while decimal is Base 10.

0.1 + 0.2; // 0.30000000000000004

A solution to this problem would be to use a function that determines if two numbers are approximately equal by defining an error margin (epsilon) value that the difference between two values should be less than.

const approxEqual = (n1, n2, epsilon = 0.0001) => Math.abs(n1 - n2) < epsilon;
approxEqual(0.1 + 0.2, 0.3); // true

Don’t forget:

What is a focus ring? What is the correct solution to handle them?

Answer

A focus ring is a visible outline given to focusable elements such as buttons and anchor tags. It varies depending on the vendor, but generally it appears as a blue outline around the element to indicate it is currently focused. In the past, many people specified outline: 0; on the element to remove the focus ring. However, this causes accessibility issues for keyboard users because the focus state may not be clear. When not specified though, it causes an unappealing blue ring to appear around an element. In recent times, frameworks like Bootstrap have opted to use a more appealing box-shadow outline to replace the default focus ring. However, this is still not ideal for mouse users. The best solution is an upcoming pseudo-selector :focus-visible which can be polyfilled today with JavaScript. It will only show a focus ring if the user is using a keyboard and leave it hidden for mouse users. This keeps both aesthetics for mouse use and accessibility for keyboard use.

Don’t forget:

What is the difference between the array methods map() and forEach()?

Answer

Both methods iterate through the elements of an array. map() maps each element to a new element by invoking the callback function on each element and returning a new array. On the other hand, forEach() invokes the callback function for each element but does not return a new array. forEach() is generally used when causing a side effect on each iteration, whereas map() is a common functional programming technique.

Don’t forget:

What are fragments?

Answer

Fragments allow a React component to return multiple elements without a wrapper, by grouping the children without adding extra elements to the DOM. Fragments offer better performance, lower memory usage, a cleaner DOM and can help in dealing with certain CSS mechanisms (e.g. tables, Flexbox and Grid).

render() {
  return (
    <React.Fragment>
      <ChildA />
      <ChildB />
      <ChildC />
    </React.Fragment>
  );
}
// Short syntax supported by Babel 7
render() {
  return (
    <>
      <ChildA />
      <ChildB />
      <ChildC />
    </>
  );
}

Don’t forget:

What is functional programming?

Answer

Functional programming is a paradigm in which programs are built in a declarative manner using pure functions that avoid shared state and mutable data. Functions that always return the same value for the same input and don’t produce side effects are the pillar of functional programming. Many programmers consider this to be the best approach to software development as it reduces bugs and cognitive load.

Don’t forget:

Describe your thoughts on how a single page web app should handle focus when changing routes

Answer

Single page applications make use of client-side rendering. This means that ‘examplesite.com’ and ‘examplesite.com/page2’ are actually the same HTML web page, but the client app decides what content to drop into that single page at runtime. Your user never actually “leaves” the page, and this causes some accessibility issues in terms of focus. Unless focus is explicitly managed in the app, a scenario like this may happen:

  1. User visits ‘examplesite.com’
  2. User clicks a link to go to another route: ‘examplesite.com/product1’
  3. Client app changes the visible content to show the details for this new route (e.g. some info about Product 1)
  4. Focus is still on the link that was clicked in step 2
  5. If a user uses the keyboard or screen reader to now try and read the content, the focused starting point is in the middle of the page on an element no longer visible Many strategies have been proposed in handling this situation, all involving explicitly managing the focus when the new page content is rendered. Recent research by GatsbyJS suggests the best approach is:
  6. User visits ‘examplesite.com’
  7. User clicks a link to go to another route: ‘examplesite.com/product1’
  8. Client app changes the visible content to show the details for this new route (e.g. some info about Product 1)
  9. Client app manually places focus on the main header at the top of the page (almost always this will be the H1 element) By doing so, focus is reset to the top of the page, ready for the user to begin exploring the new content. This solution requires inserting the main heading into the start of tabbing order with tabindex="-1".

Don’t forget:

What are higher-order components?

Answer

A higher-order component (HOC) is a function that takes a component as an argument and returns a new component. It is a pattern that is derived from React’s compositional nature. Higher-order components are like pure components because they accept any dynamically provided child component, but they won’t modify or copy any behavior from their input components.

const EnhancedComponent = higherOrderComponent(WrappedComponent);

Don’t forget:

What will the console log in this example?

var foo = 1;
var foobar = function () {
  console.log(foo);
  var foo = 2;
};
foobar();

Answer

Due to hoisting, the local variable foo is declared before the console.log method is called. This means the local variable foo is passed as an argument to console.log() instead of the global one declared outside of the function. However, since the value is not hoisted with the variable declaration, the output will be undefined, not 2.

Don’t forget:

How does hoisting work in JavaScript?

Answer

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 global or local. However, the value is not hoisted with the declaration. The following snippet:

console.log(hoist);
var hoist = "value";

is equivalent to:

var hoist;
console.log(hoist);
hoist = "value";

Therefore logging hoist outputs undefined to the console, not "value". Hoisting also allows you to invoke a function declaration before it appears to be declared in a program.

myFunction(); // No error; logs "hello"
function myFunction() {
  console.log("hello");
}

But be wary of function expressions that are assigned to a variable:

myFunction(); // Error: `myFunction` is not a function
var myFunction = function () {
  console.log("hello");
};

Don’t forget:

Answer

Yes to both. The W3 documents state that the tags represent the header(<header>) and footer(<footer>) areas of their nearest ancestor “section”. So not only can the page <body> contain a header and a footer, but so can every <article> and <section> element.

Don’t forget:

Discuss the differences between an HTML specification and a browser’s implementation thereof.

Answer

HTML specifications such as HTML5 define a set of rules that a document must adhere to in order to be “valid” according to that specification. In addition, a specification provides instructions on how a browser must interpret and render such a document. A browser is said to “support” a specification if it handles valid documents according to the rules of the specification. As of yet, no browser supports all aspects of the HTML5 specification (although all of the major browser support most of it), and as a result, it is necessary for the developer to confirm whether the aspect they are making use of will be supported by all of the browsers on which they hope to display their content. This is why cross-browser support continues to be a headache for developers, despite the improved specificiations.

Don’t forget:

What is the difference between HTML and React event handling?

Answer

In HTML, the attribute name is in all lowercase and is given a string invoking a function defined somewhere:

<button onclick="handleClick()"></button>

In React, the attribute name is camelCase and are passed the function reference inside curly braces:

<button onClick={handleClick} />

In HTML, false can be returned to prevent default behavior, whereas in React preventDefault has to be called explicitly.

<a href="#" onclick="console.log('The link was clicked.'); return false" />
function handleClick(e) {
  e.preventDefault();
  console.log("The link was clicked.");
}

Don’t forget:

What are some differences that XHTML has compared to HTML?

Answer

Some of the key differences are:

Don’t forget:

Answer

Don’t forget:

What is HTML5 Web Storage? Explain localStorage and sessionStorage.

Answer

With HTML5, web pages can store data locally within the user’s browser. The data is stored in name/value pairs, and a web page can only access data stored by itself. Differences between localStorage and sessionStorage regarding lifetime:

Don’t forget:

What is the reason for wrapping the entire contents of a JavaScript source file in a function that is immediately invoked?

Answer

This technique is very common in JavaScript libraries. It creates a closure around the entire contents of the file which creates a private namespace and thereby helps avoid potential name clashes between different JavaScript modules and libraries. The function is immediately invoked so that the namespace (library name) is assigned the return value of the function.

const myLibrary = (function () {
  var privateVariable = 2;
  return {
    publicMethod: () => privateVariable,
  };
})();
privateVariable; // ReferenceError
myLibrary.publicMethod(); // 2

Don’t forget:

Explain the differences between imperative and declarative programming.

Answer

These two types of programming can roughly be summarized as:

Imperative

const numbers = [1, 2, 3, 4, 5];
const numbersDoubled = [];
for (let i = 0; i < numbers.length; i++) {
  numbersDoubled[i] = numbers[i] * 2;
}

We manually loop over the numbers of the array and assign the new index as the number doubled.

Declarative

const numbers = [1, 2, 3, 4, 5];
const numbersDoubled = numbers.map((n) => n * 2);

We declare that the new array is mapped to a new one where each value is doubled.

Don’t forget:

What are inline conditional expressions?

Answer

Since a JSX element tree is one large expression, you cannot embed statements inside. Conditional expressions act as a replacement for statements to use inside the tree. For example, this won’t work:

function App({ messages, isVisible }) {
  return (
    <div>
      if (messages.length > 0){" "}
      {<h2>You have {messages.length} unread messages.</h2>} else{" "}
      {<h2>You have no unread messages.</h2>}
      if (isVisible) {<p>I am visible.</p>}
    </div>
  );
}

Logical AND && and the ternary ? : operator replace the if/else statements.

function App({ messages, isVisible }) {
  return (
    <div>
      {messages.length > 0 ? (
        <h2>You have {messages.length} unread messages.</h2>
      ) : (
        <h2>You have no unread messages.</h2>
      )}
      {isVisible && <p>I am visible.</p>}
    </div>
  );
}

Don’t forget:

What is a key? What are the benefits of using it in lists?

Answer

Keys are a special string attribute that helps React identify which items have been changed, added or removed. They are used when rendering array elements to give them a stable identity. Each element’s key must be unique (e.g. IDs from the data or indexes as a last resort).

const todoItems = todos.map((todo) => <li key={todo.id}>{todo.text}</li>);

Don’t forget:

What are landmark roles and how can they be useful?

Answer

Landmark roles is a way to identify different sections of a page like the main content or a navigation region. The Landmarks helps assistive technology users to navigate a page, allowing them skip over areas of it. For example,

<div id="header" role="banner">Header of the Page</div>
<div id="content" role="main">Main Content Goes Here</div>

Don’t forget:

What is the difference between lexical scoping and dynamic scoping?

Answer

Lexical scoping refers to when the location of a function’s definition determines which variables you have access to. On the other hand, dynamic scoping uses the location of the function’s invocation to determine which variables are available.

Don’t forget:

What are the lifecycle methods in React?

Answer

getDerivedStateFromProps: Executed before rendering on the initial mount and all component updates. Used to update the state based on changes in props over time. Has rare use cases, like tracking component animations during the lifecycle. There are only few cases where this makes sense to use over other lifecycle methods. It expects to return an object that will be the the new state, or null to update nothing. This method does not have access to the component instance either. componentDidMount: Executed after first rendering and here all AJAX requests, DOM or state updates, and set up eventListeners should occur. shouldComponentUpdate: Determines if the component will be updated or not. By default, it returns true. If you are sure that the component doesn’t need to render after state or props are updated, you can return a false value. It is a great place to improve performance as it allows you to prevent a rerender if component receives new prop. getSnapshotBeforeUpdate: Invoked right after a component render happens because of an update, before componentDidUpdate. Any value returned from this method will be passed to componentDidUpdate. componentDidUpdate: Mostly it is used to update the DOM in response to prop or state changes. componentWillUnmount: It will be used to cancel any outgoing network requests, or remove all event listeners associated with the component. componentDidCatch: Used in error boundaries, which are components that implement this method. It allows the component to catch JavaScript errors anywhere in the child component tree (below this component), log errors, and display a UI with error information.

Don’t forget:

What are the different phases of the component lifecycle in React?

Answer

There are four different phases of component’s lifecycle: Initialization: In this phase, the component prepares setting up the initial state and default props. Mounting: The react component is ready to mount to the DOM. This phase covers the getDerivedStateFromProps and componentDidMount lifecycle methods. Updating: In this phase, the component gets updated in two ways, sending the new props and updating the state. This phase covers the getDerivedStateFromProps, shouldComponentUpdate, getSnapshotBeforeUpdate and componentDidUpdate lifecycle methods. Unmounting: In this last phase, the component is not needed and gets unmounted from the browser DOM. This phase includes the componentWillUnmount lifecycle method. Error Handling: In this phase, the component is called whenever there’s an error during rendering, in a lifecycle method, or in the constructor for any child component. This phase includes the componentDidCatch lifecycle method.

Don’t forget:

What does lifting state up in React mean?

Answer

When several components need to share the same data, then it is recommended to lift the shared state up to their closest common ancestor. For example, if two child components share the same data, it is recommended to move the shared state to parent instead of maintaining the local state in both child components.

Don’t forget:

Create a function that masks a string of characters with # except for the last four (4) characters.

mask("123456789"); // "#####6789"

Answer

There are many ways to solve this problem, this is just one one of them. Using String.prototype.slice() we can grab the last 4 characters of the string by passing -4 as an argument. Then, using String.prototype.padStart(), we can pad the string to the original length with the repeated mask character.

const mask = (str, maskChar = "#") =>
  str.slice(-4).padStart(str.length, maskChar);

Don’t forget:

Can you name the four types of @media properties?

Answer

Don’t forget:

What is memoization?

Answer

Memoization is the process of caching the output of function calls so that subsequent calls are faster. Calling the function again with the same input will return the cached output without needing to do the calculation again. A basic implementation in JavaScript looks like this:

const memoize = (fn) => {
  const cache = new Map();
  return (value) => {
    const cachedResult = cache.get(value);
    if (cachedResult !== undefined) return cachedResult;
    const result = fn(value);
    cache.set(value, result);
    return result;
  };
};

Don’t forget:

How do you ensure methods have the correct this context in React component classes?

Answer

In JavaScript classes, the methods are not bound by default. This means that their this context can be changed (in the case of an event handler, to the element that is listening to the event) and will not refer to the component instance. To solve this, Function.prototype.bind() can be used to enforce the this context as the component instance.

constructor(props) {
  super(props);
  this.handleClick = this.handleClick.bind(this);
}
handleClick() {
  // Perform some logic
}
handleClick = () => {
  console.log('this is:', this);
}
render() {
  return (
    <button onClick={this.handleClick}>
      Click me
    </button>
  );
}
<button onClick={(e) => this.handleClick(e)}>Click me</button>

Note that extra re-rendering can occur using this technique because a new function reference is created on render, which gets passed down to child components and breaks shouldComponentUpdate / PureComponent shallow equality checks to prevent unnecessary re-renders. In cases where performance is important, it is preferred to go with bind in the constructor, or the public class fields syntax approach, because the function reference remains constant.

Don’t forget:

What is a MIME type and what is it used for?

Answer

MIME is an acronym for Multi-purpose Internet Mail Extensions. It is used as a standard way of classifying file types over the Internet.

Don’t forget:

Contrast mutable and immutable values, and mutating vs non-mutating methods.

Answer

The two terms can be contrasted as:

const myString = "hello!";
myString.replace("!", ""); // returns a new string, cannot mutate the original value
const originalArray = [1, 2, 3];
originalArray.push(4); // mutates originalArray, now [1, 2, 3, 4]
originalArray.concat(4); // returns a new array, does not mutate the original

Don’t forget:

What is the only value not equal to itself in JavaScript?

Answer

NaN (Not-a-Number) is the only value not equal to itself when comparing with any of the comparison operators. NaN is often the result of meaningless math computations, so two NaN values make no sense to be considered equal.

Don’t forget:

NodeJS often uses a callback pattern where if an error is encountered during execution, this error is passed as the first argument to the callback. What are the advantages of this pattern?

fs.readFile(filePath, function (err, data) {
  if (err) {
    // handle the error, the return is important here
    // so execution stops here
    return console.log(err);
  }
  // use the data object
  console.log(data);
});

Answer

Advantages include:

var isTrue = function (value, callback) {
  if (value === true) {
    callback(null, "Value was true.");
  } else {
    callback(new Error("Value is not true!"));
  }
};
var callback = function (error, retval) {
  if (error) {
    console.log(error);
    return;
  }
  console.log(retval);
};
isTrue(false, callback);
isTrue(true, callback);
/*
  { stack: [Getter/Setter],
    arguments: undefined,
    type: undefined,
    message: 'Value is not true!' }
  Value was true.
*/

Don’t forget:

What is the event loop in Node.js?

Answer

The event loop handles all async callbacks. Callbacks are queued in a loop, while other code runs, and will run one by one when the response for each one has been received.

Don’t forget:

What is the difference between null and undefined?

Answer

In JavaScript, two values discretely represent nothing - undefined and null. The concrete difference between them is that null is explicit, while undefined is implicit. When a property does not exist or a variable has not been given a value, the value is undefined. null is set as the value to explicitly indicate “no value”. In essence, undefined is used when the nothing is not known, and null is used when the nothing is known.

Don’t forget:

Describe the different ways to create an object. When should certain ways be preferred over others?

Answer

Object literal

Often used to store one occurrence of data.

const person = {
  name: "John",
  age: 50,
  birthday() {
    this.age++;
  },
};
person.birthday(); // person.age === 51

Constructor

Often used when you need to create multiple instances of an object, each with their own data that other instances of the class cannot affect. The new operator must be used before invoking the constructor or the global object will be mutated.

function Person(name, age) {
  this.name = name;
  this.age = age;
}
Person.prototype.birthday = function () {
  this.age++;
};
const person1 = new Person("John", 50);
const person2 = new Person("Sally", 20);
person1.birthday(); // person1.age === 51
person2.birthday(); // person2.age === 21

Factory function

Creates a new object similar to a constructor, but can store private data using a closure. There is also no need to use new before invoking the function or the this keyword. Factory functions usually discard the idea of prototypes and keep all properties and methods as own properties of the object.

const createPerson = (name, age) => {
  const birthday = () => person.age++;
  const person = { name, age, birthday };
  return person;
};
const person = createPerson("John", 50);
person.birthday(); // person.age === 51

Object.create()

Sets the prototype of the newly created object.

const personProto = {
  birthday() {
    this.age++;
  },
};
const person = Object.create(personProto);
person.age = 50;
person.birthday(); // person.age === 51

A second argument can also be supplied to Object.create() which acts as a descriptor for the new properties to be defined.

Object.create(personProto, {
  age: {
    value: 50,
    writable: true,
    enumerable: true,
  },
});

Don’t forget:

What is the difference between a parameter and an argument?

Answer

Parameters are the variable names of the function definition, while arguments are the values given to a function when it is invoked.

function myFunction(parameter1, parameter2) {
  console.log(arguments[0]); // "argument1"
}
myFunction("argument1", "argument2");

Don’t forget:

Does JavaScript pass by value or by reference?

Answer

JavaScript always passes by value. However, with objects, the value is a reference to the object.

Don’t forget:

How do you pass an argument to an event handler or callback?

Answer

You can use an arrow function to wrap around an event handler and pass arguments, which is equivalent to calling bind:

<button onClick={() => this.handleClick(id)} />
<button onClick={this.handleClick.bind(this, id)} />

Don’t forget:

Create a function pipe that performs left-to-right function composition by returning a function that accepts one argument.

const square = (v) => v * v;
const double = (v) => v * 2;
const addOne = (v) => v + 1;
const res = pipe(square, double, addOne);
res(3); // 19; addOne(double(square(3)))

Answer

Gather all supplied arguments using the rest operator ... and return a unary function that uses Array.prototype.reduce() to run the value through the series of functions before returning the final value.

const pipe =
  (...fns) =>
  (x) =>
    fns.reduce((v, fn) => fn(v), x);

Don’t forget:

What are portals in React?

Answer

Portal are the recommended way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.

ReactDOM.createPortal(child, container);

The first argument (child) is any renderable React child, such as an element, string, or fragment. The second argument (container) is a DOM element.

Don’t forget:

What is the difference between the postfix i++ and prefix ++i increment operators?

Answer

Both increment the variable value by 1. The difference is what they evaluate to. The postfix increment operator evaluates to the value before it was incremented.

let i = 0;
i++; // 0
// i === 1

The prefix increment operator evaluates to the value after it was incremented.

let i = 0;
++i; // 1
// i === 1

Don’t forget:

In which states can a Promise be?

Answer

A Promise is in one of these states:

Don’t forget:

What are Promises?

Answer

The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value. An example can be the following snippet, which after 100ms prints out the result string to the standard output. Also, note the catch, which can be used for error handling. Promises are chainable.

new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("result");
  }, 100);
})
  .then(console.log)
  .catch(console.error);

Don’t forget:

How to apply prop validation in React?

Answer

When the application is running in development mode, React will automatically check for all props that we set on components to make sure they are the correct data type. For incorrect data types, it will generate warning messages in the console for development mode. They are stripped in production mode due to their performance impact. Required props are defined with isRequired. For example, we define propTypes for component as below:

import PropTypes from "prop-types"
class User extends React.Component {
  static propTypes = {
    name: PropTypes.string.isRequired,
    age: PropTypes.number.isRequired
  }
  render() {
    return (
      <h1>Welcome, {this.props.name}</h1>
      <h2>Age, {this.props.age}
    )
  }
}

Don’t forget:

How does prototypal inheritance differ from classical inheritance?

Answer

In the classical inheritance paradigm, object instances inherit their properties and functions from a class, which acts as a blueprint for the object. Object instances are typically created using a constructor and the new keyword. In the prototypal inheritance paradigm, object instances inherit directly from other objects and are typically created using factory functions or Object.create().

Don’t forget:

What is a pure function?

Answer

A pure function is a function that satisfies these two conditions:

Pure

const a = (x, y) => x + y;
const b = (arr, value) => arr.concat(value);
const c = (arr) => [...arr].sort((a, b) => a - b);

Impure

const a = (x, y) => x + y + Math.random();
const b = (arr, value) => (arr.push(value), arr);
const c = (arr) => arr.sort((a, b) => a - b);

Don’t forget:

How do you write comments inside a JSX tree in React?

Answer

Comments must be wrapped inside curly braces {} and use the /* */ syntax.

const tree = (
  <div>
    {/* Comment */}
    <p>Text</p>
  </div>
);

What is recursion and when is it useful?

Answer

Recursion is the repeated application of a process. In JavaScript, recursion involves functions that call themselves repeatedly until they reach a base condition. The base condition breaks out of the recursion loop because otherwise the function would call itself indefinitely. Recursion is very useful when working with data structures that contain nesting where the number of levels deep is unknown. For example, you may have a thread of comments returned from a database that exist in a flat array but need to be nested for display in the UI. Each comment is either a top-level comment (no parent) or is a reply to a parent comment. Comments can be a reply of a reply of a reply… we have no knowledge beforehand the number of levels deep a comment may be. This is where recursion can help.

const nest = (items, id = null, link = "parent_id") =>
  items
    .filter((item) => item[link] === id)
    .map((item) => ({ ...item, children: nest(items, item.id) }));
const comments = [
  { id: 1, parent_id: null, text: "First reply to post." },
  { id: 2, parent_id: 1, text: "First reply to comment #1." },
  { id: 3, parent_id: 1, text: "Second reply to comment #1." },
  { id: 4, parent_id: 3, text: "First reply to comment #3." },
  { id: 5, parent_id: 4, text: "First reply to comment #4." },
  { id: 6, parent_id: null, text: "Second reply to post." },
];
nest(comments);
/*
[
  { id: 1, parent_id: null, text: "First reply to post.", children: [...] },
  { id: 6, parent_id: null, text: "Second reply to post.", children: [] }
]
*/

In the above example, the base condition is met if filter() returns an empty array. The chained map() won’t invoke the callback function which contains the recursive call, thereby breaking the loop.

Don’t forget:

What is the output of the following code?

const a = [1, 2, 3];
const b = [1, 2, 3];
const c = "1,2,3";
console.log(a == c);
console.log(a == b);

Answer

The first console.log outputs true because JavaScript’s compiler performs type conversion and therefore it compares to strings by their value. On the other hand, the second console.log outputs false because Arrays are Objects and Objects are compared by reference.

Don’t forget:

What are refs in React? When should they be used?

Answer

Refs provide a way to access DOM nodes or React elements created in the render method. Refs should be used sparringly, but there are some good use cases for refs, such as:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
  render() {
    return <div ref={this.myRef} />;
  }
}

Refs can also be used in functional components with the help of closures.

Don’t forget:

Where and why is the rel="noopener" attribute used?

Answer

The rel="noopener" is an attribute used in <a> elements (hyperlinks). It prevents pages from having a window.opener property, which would otherwise point to the page from where the link was opened and would allow the page opened from the hyperlink to manipulate the page where the hyperlink is.

Don’t forget:

What is REST?

Answer

REST (REpresentational State Transfer) is a software design pattern for network architecture. A RESTful web application exposes data in the form of information about its resources. Generally, this concept is used in web applications to manage state. With most applications, there is a common theme of reading, creating, updating, and destroying data. Data is modularized into separate tables like posts, users, comments, and a RESTful API exposes access to this data with:

Don’t forget:

What does the following function return?

function greet() {
  return;
  {
    message: "hello";
  }
}

Answer

Because of JavaScript’s automatic semicolon insertion (ASI), the compiler places a semicolon after return keyword and therefore it returns undefined without an error being thrown.

Don’t forget:

Are semicolons required in JavaScript?

Answer

Sometimes. Due to JavaScript’s automatic semicolon insertion, the interpreter places semicolons after most statements. This means semicolons can be omitted in most cases. However, there are some cases where they are required. They are not required at the beginning of a block, but are if they follow a line and:

  1. The line starts with [
const previousLine = 3;
[1, 2, previousLine].map((n) => n * 2);
  1. The line starts with (
const previousLine = 3;
(function () {
  // ...
})();

In the above cases, the interpreter does not insert a semicolon after 3, and therefore it will see the 3 as attempting object property access or being invoked as a function, which will throw errors.

Don’t forget:

What is short-circuit evaluation in JavaScript?

Answer

Short-circuit evaluation involves logical operations evaluating from left-to-right and stopping early.

true || false;

In the above sample using logical OR, JavaScript won’t look at the second operand false, because the expression evaluates to true regardless. This is known as short-circuit evaluation. This also works for logical AND.

false && true;

This means you can have an expression that throws an error if evaluated, and it won’t cause issues.

true || nonexistentFunction();
false && nonexistentFunction();

This remains true for multiple operations because of left-to-right evaluation.

true || nonexistentFunction() || window.nothing.wouldThrowError;
true || window.nothing.wouldThrowError;
true;

A common use case for this behavior is setting default values. If the first operand is falsy the second operand will be evaluated.

const options = {};
const setting = options.setting || "default";
setting; // "default"

Another common use case is only evaluating an expression if the first operand is truthy.

// Instead of:
addEventListener("click", (e) => {
  if (e.target.closest("button")) {
    handleButtonClick(e);
  }
});
// You can take advantage of short-circuit evaluation:
addEventListener(
  "click",
  (e) => e.target.closest("button") && handleButtonClick(e)
);

In the above case, if e.target is not or does not contain an element matching the "button" selector, the function will not be called. This is because the first operand will be falsy, causing the second operand to not be evaluated.

Don’t forget:

What are the advantages of using CSS sprites and how are they utilized?

Answer

CSS sprites combine multiple images into one image, limiting the number of HTTP requests a browser has to make, thus improving load times. Even under the new HTTP/2 protocol, this remains true. Under HTTP/1.1, at most one request is allowed per TCP connection. With HTTP/1.1, modern browsers open multiple parallel connections (between 2 to 8) but it is limited. With HTTP/2, all requests between the browser and the server are multiplexed on a single TCP connection. This means the cost of opening and closing multiple connections is mitigated, resulting in a better usage of the TCP connection and limits the impact of latency between the client and server. It could then become possible to load tens of images in parallel on the same TCP connection. However, according to benchmark results, although HTTP/2 offers 50% improvement over HTTP/1.1, in most cases the sprite set is still faster to load than individual images. To utilize a spritesheet in CSS, one would use certain properties, such as background-image, background-position and background-size to ultimately alter the background of an element.

Don’t forget:

What is a stateful component in React?

Answer

A stateful component is a component whose behavior depends on its state. This means that two separate instances of the component if given the same props will not necessarily render the same output, unlike pure function components.

// Stateful class component
class App extends Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }
  render() {
    // ...
  }
}
// Stateful function component
function App() {
  const [count, setCount] = useState(0);
  return; // ...
}

Don’t forget:

What is a stateless component?

Answer

A stateless component is a component whose behavior does not depend on its state. Stateless components can be either functional or class components. Stateless functional components are easier to maintain and test since they are guaranteed to produce the same output given the same props. Stateless functional components should be preferred when lifecycle hooks don’t need to be used.

Don’t forget:

Explain the difference between a static method and an instance method.

Answer

Static methods belong to a class and don’t act on instances, while instance methods belong to the class prototype which is inherited by all instances of the class and acts on them.

Array.isArray; // static method of Array
Array.prototype.push; // instance method of Array

In this case, the Array.isArray method does not make sense as an instance method of arrays because we already know the value is an array when working with it. Instance methods could technically work as static methods, but provide terser syntax:

const arr = [1, 2, 3];
arr.push(4);
Array.push(arr, 4);

Don’t forget:

What is the difference between synchronous and asynchronous code in JavaScript?

Answer

Synchronous means each operation must wait for the previous one to complete. Asynchronous means an operation can occur while another operation is still being processed. In JavaScript, all code is synchronous due to the single-threaded nature of it. However, asynchronous operations not part of the program (such as XMLHttpRequest or setTimeout) are processed outside of the main thread because they are controlled by native code (browser APIs), but callbacks part of the program will still be executed synchronously.

Don’t forget:

What is the this keyword and how does it work?

Answer

The this keyword is an object that represents the context of an executing function. Regular functions can have their this value changed with the methods call(), apply() and bind(). Arrow functions implicitly bind this so that it refers to the context of its lexical environment, regardless of whether or not its context is set explicitly with call(). Here are some common examples of how this works:

Object literals

this refers to the object itself inside regular functions if the object precedes the invocation of the function. Properties set as this do not refer to the object.

var myObject = {
  property: this,
  regularFunction: function () {
    return this;
  },
  arrowFunction: () => {
    return this;
  },
  iife: (function () {
    return this;
  })(),
};
myObject.regularFunction(); // myObject
myObject["regularFunction"](); // my Object
myObject.property; // NOT myObject; lexical `this`
myObject.arrowFunction(); // NOT myObject; lexical `this`
myObject.iife; // NOT myObject; lexical `this`
const regularFunction = myObject.regularFunction;
regularFunction(); // NOT myObject; lexical `this`

Event listeners

this refers to the element listening to the event.

document.body.addEventListener("click", function () {
  console.log(this); // document.body
});

Constructors

this refers to the newly created object.

class Example {
  constructor() {
    console.log(this); // myExample
  }
}
const myExample = new Example();

Manual

With call() and apply(), this refers to the object passed as the first argument.

var myFunction = function () {
  return this;
};
myFunction.call({ customThis: true }); // { customThis: true }

Unwanted this

Because this can change depending on the scope, it can have unexpected values when using regular functions.

var obj = {
  arr: [1, 2, 3],
  doubleArr() {
    return this.arr.map(function (value) {
      // this is now this.arr
      return this.double(value);
    });
  },
  double() {
    return value * 2;
  },
};
obj.doubleArr(); // Uncaught TypeError: this.double is not a function

Don’t forget:

What does the following code evaluate to?

typeof typeof 0;

Answer

It evaluates to "string". typeof 0 evaluates to the string "number" and therefore typeof "number" evaluates to "string".

Don’t forget:

What are JavaScript data types?

Answer

The latest ECMAScript standard defines seven data types, six of them being primitive: Boolean, Null, Undefined, Number, String, Symbol and one non-primitive data type: Object.

Don’t forget:

What is the purpose of JavaScript UI libraries/frameworks like React, Vue, Angular, Hyperapp, etc?

Answer

The main purpose is to avoid manipulating the DOM directly and keep the state of an application in sync with the UI easily. Additionally, they provide the ability to create components that can be reused when they have similar functionality with minor differences, avoiding duplication which would require multiple changes whenever the structure of a component which is reused in multiple places needs to be updated. When working with DOM manipulation libraries like jQuery, the data of an application is generally kept in the DOM itself, often as class names or data attributes. Manipulating the DOM to update the UI involves many extra steps and can introduce subtle bugs over time. Keeping the state separate and letting a framework handle the UI updates when the state changes reduces cognitive load. Saying you want the UI to look a certain way when the state is a certain value is the declarative way of creating an application, instead of the imperative way of manually updating the UI to reflect the new state.

Don’t forget:

What does 'use strict' do and what are some of the key benefits to using it?

Answer

Including 'use strict' at the beginning of your JavaScript source file enables strict mode, which enforces more strict parsing and error handling of JavaScript code. It is considered a good practice and offers a lot of benefits, such as:

Don’t forget:

What are the differences between var, let, const and no keyword statements?

Answer

No keyword

When no keyword exists before a variable assignment, it is either assigning a global variable if one does not exist, or reassigns an already declared variable. In non-strict mode, if the variable has not yet been declared, it will assign the variable as a property of the global object (window in browsers). In strict mode, it will throw an error to prevent unwanted global variables from being created.

var

var was the default statement to declare a variable until ES2015. It creates a function-scoped variable that can be reassigned and redeclared. However, due to its lack of block scoping, it can cause issues if the variable is being reused in a loop that contains an asynchronous callback because the variable will continue to exist outside of the block scope. Below, by the time the the setTimeout callback executes, the loop has already finished and the i variable is 10, so all ten callbacks reference the same variable available in the function scope.

for (var i = 0; i < 10; i++) {
  setTimeout(() => {
    // logs `10` ten times
    console.log(i);
  });
}
/* Solutions with `var` */
for (var i = 0; i < 10; i++) {
  // Passed as an argument will use the value as-is in
  // that point in time
  setTimeout(console.log, 0, i);
}
for (var i = 0; i < 10; i++) {
  // Create a new function scope that will use the value
  // as-is in that point in time
  ((i) => {
    setTimeout(() => {
      console.log(i);
    });
  })(i);
}

let

let was introduced in ES2015 and is the new preferred way to declare variables that will be reassigned later. Trying to redeclare a variable again will throw an error. It is block-scoped so that using it in a loop will keep it scoped to the iteration.

for (let i = 0; i < 10; i++) {
  setTimeout(() => {
    // logs 0, 1, 2, 3, ...
    console.log(i);
  });
}

const

const was introduced in ES2015 and is the new preferred default way to declare all variables if they won’t be reassigned later, even for objects that will be mutated (as long as the reference to the object does not change). It is block-scoped and cannot be reassigned.

const myObject = {};
myObject.prop = "hello!"; // No error
myObject = "hello"; // Error

Don’t forget:

What is a virtual DOM and why is it used in libraries/frameworks?

Answer

The virtual DOM (VDOM) is a representation of the real DOM in the form of plain JavaScript objects. These objects have properties to describe the real DOM nodes they represent: the node name, its attributes, and child nodes.

<div class="counter">
  <h1>0</h1>
  <button>-</button>
  <button>+</button>
</div>

The above markup’s virtual DOM representation might look like this:

{
  nodeName: "div",
  attributes: { class: "counter" },
  children: [
    {
      nodeName: "h1",
      attributes: {},
      children: [0]
    },
    {
      nodeName: "button",
      attributes: {},
      children: ["-"]
    },
    {
      nodeName: "button",
      attributes: {},
      children: ["+"]
    }
  ]
}

The library/framework uses the virtual DOM as a means to improve performance. When the state of an application changes, the real DOM needs to be updated to reflect it. However, changing real DOM nodes is costly compared to recalculating the virtual DOM. The previous virtual DOM can be compared to the new virtual DOM very quickly in comparison. Once the changes between the old VDOM and new VDOM have been calculated by the diffing engine of the framework, the real DOM can be patched efficiently in the least time possible to match the new state of the application.

Don’t forget:

What is WCAG? What are the differences between A, AA, and AAA compliance?

Answer

WCAG stands for “Web Content Accessibility Guidelines”. It is a standard describing how to make web content more accessible to people with disabilities They have 12-13 guidelines and for each one, there are testable success criteria, which are at three levels: A, AA, and AAA. The higher the level, the higher the impact on the design of the web content. The higher the level, the web content is essentially more accessible by more users. Depending on where you live/work, there may be regulations requiring websites to meet certain levels of compliance. For instance, in Ontario, Canada, beginning January 1, 2021 all public websites and web content posted after January 1, 2012 must meet AA compliance.

Don’t forget:

What is a cross-site scripting attack (XSS) and how do you prevent it?

Answer

XSS refers to client-side code injection where the attacker injects malicious scripts into a legitimate website or web application. This is often achieved when the application does not validate user input and freely injects dynamic HTML content. For example, a comment system will be at risk if it does not validate or escape user input. If the comment contains unescaped HTML, the comment can inject a <script> tag into the website that other users will execute against their knowledge.

Don’t forget:


ALL Prior Code:

// Normal promises in regular function:
function foo() {
  promiseCall()
    .then(result => {
      // do something with the result
    })
}
// async functions
async function foo() {
  const result = await promiseCall()
  // do something with the result
}
/**
It accepts two objects as arguments: the first object is the recipe
for the food, while the second object is the available ingredients.
Each ingredient's value is a number representing how many units there are.
`batches(recipe, available)`
*/
// 0 batches can be made
batches(
  { milk: 100, butter: 50, flour: 5 },
  { milk: 132, butter: 48, flour: 51 }
)
batches(
  { milk: 100, flour: 4, sugar: 10, butter: 5 },
  { milk: 1288, flour: 9, sugar: 95 }
)
// 1 batch can be made
batches(
  { milk: 100, butter: 50, cheese: 10 },
  { milk: 198, butter: 52, cheese: 10 }
)
// 2 batches can be made
batches(
  { milk: 2, sugar: 40, butter: 20 },
  { milk: 5, sugar: 120, butter: 500 }
)
const batches = (recipe, available) =>
  Math.floor(
    Math.min(...Object.keys(recipe).map(k => available[k] / recipe[k] || 0))
  )
arr[arr.length - 1]
arr.filter(fn)
arr.some(fn)
arr.sort(fn)
for (let i = 0; i < arr.length; i++) {
  for (let j = 0; j < arr.length; j++) {
    // ...
  }
}
const permutations = arr => {
  if (arr.length <= 2) return arr.length === 2 ? [arr, [arr[1], arr[0]]] : arr
  return arr.reduce(
    (acc, item, i) =>
      acc.concat(
        permutations([...arr.slice(0, i), ...arr.slice(i + 1)]).map(val => [
          item,
          ...val
        ])
      ),
    []
  )
}
function example() {
  console.log(this)
}
const boundExample = bind(example, { a: true })
boundExample.call({ b: true }) // logs { a: true }
const bind = (fn, context) => (...args) => fn.apply(context, args)
getData(function(a) {
  getMoreData(a, function(b) {
    getMoreData(b, function(c) {
      getMoreData(c, function(d) {
        getMoreData(d, function(e) {
          // ...
        })
      })
    })
  })
})
async function asyncAwaitVersion() {
  const a = await getData()
  const b = await getMoreData(a)
  const c = await getMoreData(b)
  const d = await getMoreData(c)
  const e = await getMoreData(d)
  // ...
}
setState({ name: "sudheer" }, () => {
  console.log("The name has updated and component re-rendered")
})
// Legacy approach using findDOMNode()
class MyComponent extends Component {
  componentDidMount() {
    findDOMNode(this).scrollIntoView()
  }
  render() {
    return <div />
  }
}
// Recommended approach using callback refs
class MyComponent extends Component {
  componentDidMount() {
    this.node.scrollIntoView()
  }
  render() {
    return <div ref={node => (this.node = node)} />
  }
}
function onClick() {
  console.log("The user clicked on the page.")
}
document.addEventListener("click",
    onClick)
const map = (arr, callback) => {
  const result = []
  for (let i = 0; i < arr.length; i++) {
    result.push(callback(arr[i], i))
  }
  return result
}
map([1, 2, 3, 4, 5], n => n * 2) // [2, 4, 6, 8, 10]
function GenericBox({ children }) {
  return <div className="container">{children}</div>
}
function App() {
  return (
    <GenericBox>
      <span>Hello</span> <span>World</span>
    </GenericBox>
  )
}
const element = document.createElement("div")
element.className = "hello"
const element = {
  attributes: {
    class: "hello"
  }
}
const { class } = this.props // Error
const { className } = this.props // All good
const { class: className } =
    this.props // All good, but
const obj = { a: 1, b: 2 }
const shallowClone = { ...obj }
function isDeepEqual(obj1, obj2, testPrototypes = false) {
  if (obj1 === obj2) {
    return true
  }
  if (typeof obj1 === "function" && typeof obj2 === "function") {
    return obj1.toString() === obj2.toString()
  }
  if (obj1 instanceof Date && obj2 instanceof Date) {
    return obj1.getTime() === obj2.getTime()
  }
  if (
    Object.prototype.toString.call(obj1) !==
      Object.prototype.toString.call(obj2) ||
    typeof obj1 !== "object"
  ) {
    return false
  }
  const prototypesAreEqual = testPrototypes
    ? isDeepEqual(
        Object.getPrototypeOf(obj1),
        Object.getPrototypeOf(obj2),
        true
      )
    : true
  const obj1Props = Object.getOwnPropertyNames(obj1)
  const obj2Props = Object.getOwnPropertyNames(obj2)
  return (
    obj1Props.length === obj2Props.length &&
    prototypesAreEqual &&
    obj1Props.every(prop => isDeepEqual(obj1[prop], obj2[prop]))
  )
}
const { Provider, Consumer } = React.createContext(defaultValue)
const debounce = (func, delay) => {
  let debounceTimer;
  return function() {
    const context = this;
    const args = arguments;
      clearTimeout(debounceTimer);
        debounceTimer = setTimeout(() => func.apply(context, args), delay);
  }
}
window.addEventListere('scroll', debounce(function() {
  // Do stuff, this function will be called after a delay of 1 second
}, 1000));
const Component = () => "Hello"
const componentElement = <Component />
const domNodeElement = <div />
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props)
    this.state = { hasError: false }
  }
  // Use componentDidCatch to log the error
  componentDidCatch(error, info) {
    // You can also log the error to an error reporting service
    logErrorToMyService(error, info)
  }
  // use getDerivedStateFromError to update state
  static getDerivedStateFromError(error) {
    // Display fallback UI
     return { hasError: true };
  }
  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>
    }
    return this.props.children
  }
}
document.querySelectorAll("button").forEach(button => {
  button.addEventListener("click", handleButtonClick)
})
document.addEventListener("click", e => {
  if (e.target.closest("button")) {
    handleButtonClick()
  }
})
document.addEventListener("click", function(event) {
  // This callback function is run when the user
  // clicks on the document.
})
const hub = createEventHub()
hub.on("message", function(data) {
  console.log(`${data.username} said ${data.text}`)
})
hub.emit("message", {
  username: "John",
  text: "Hello?"
})
let x = 0
function declaration() {}
if (true) {
}
// Assign `x` to the absolute value of `y`.
var x
if (y >= 0) {
  x = y
} else {
  x = -y
}
5 + 5 // => 10
lastCharacter("input") // => "t"
true === true // => true
// Assign `x` as the absolute value of `y`.
var x = y >= 0 ? y : -y
Boolean("") // false
Boolean([]) // true
!!"" // false
!![] // true
const fibonacci = n =>
  [...Array(n)].reduce(
    (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i),
    []
  )
const words = ['rates', 'rat', 'stare', 'taser', 'tears', 'art', 'tabs', 'tar', 'bats', 'state'];
const words = ['rates', 'rat', 'stare', 'taser', 'tears', 'art', 'tabs', 'tar', 'bats', 'state'];
function anagramGroups(wordAry){
    const groupedWords = {};
    // iterate over each word in the array
    wordAry.map(word => {
      // alphabetize the word and a separate variable
      alphaWord = word.split('').sort().join('');
      // if the alphabetize word is already a key, push the actual word value (this is an anagram)
      if(groupedWords[alphaWord]) {
        return groupedWords[alphaWord].push(word);
      }
      // otherwise add the alphabetize word key and actual word value (may not turn out to be an anagram)
      groupedWords[alphaWord] = [word];
    })
    return groupedWords;
}
// call the function and store results in a variable called collectedAnagrams
const collectedAnagrams = anagramGroups(words);
// iterate over groupedAnagrams, printing out group of values
for(const sortedWord in collectedAnagrams) {
  if(collectedAnagrams[sortedWord].length > 1) {
    console.log(collectedAnagrams[sortedWord].toString());
  }
}
0.1 + 0.2 // 0.30000000000000004
const approxEqual = (n1, n2, epsilon = 0.0001) => Math.abs(n1 - n2) < epsilon
approxEqual(0.1 + 0.2, 0.3) // true
render() {
  return (
    <React.Fragment>
      <ChildA />
      <ChildB />
      <ChildC />
    </React.Fragment>
  )
};
// Short syntax supported by Babel 7
render() {
 return (
    <>
      <ChildA />
      <ChildB />
      <ChildC />
    </>
  );
};
const EnhancedComponent = higherOrderComponent(WrappedComponent)
var foo = 1
var foobar = function() {
  console.log(foo)
  var foo = 2
}
foobar()
console.log(hoist)
var hoist = "value"
var hoist
console.log(hoist)
hoist = "value"
myFunction() // No error; logs "hello"
function myFunction() {
  console.log("hello")
}
myFunction() // Error: `myFunction` is not a function
var myFunction = function() {
  console.log("hello")
}
const myLibrary = (function() {
  var privateVariable = 2
  return {
    publicMethod: () => privateVariable
  }
})()
privateVariable // ReferenceError
myLibrary.publicMethod() // 2
const numbers = [1, 2, 3, 4, 5]
const numbersDoubled = []
for (let i = 0; i < numbers.length; i++) {
  numbersDoubled[i] = numbers[i] * 2
}
const numbers = [1, 2, 3, 4, 5]
const numbersDoubled = numbers.map(n => n * 2)
function App({ messages, isVisible }) {
  return (
    <div>
      if (messages.length > 0) {
        <h2>You have {messages.length} unread messages.</h2>
      } else {
        <h2>You have no unread messages.</h2>
      }
      if (isVisible) {
        <p>I am visible.</p>
      }
    </div>
  )
}
function App({ messages, isVisible }) {
  return (
    <div>
      {messages.length > 0 ? (
        <h2>You have {messages.length} unread messages.</h2>
      ) : (
        <h2>You have no unread messages.</h2>
      )}
      {isVisible && <p>I am visible.</p>}
    </div>
  )
}
const todoItems = todos.map(todo => <li key={todo.id}>{todo.text}</li>)
const mask = (str, maskChar = "#") =>
  str.slice(-4).padStart(str.length, maskChar)
const memoize = fn => {
  const cache = new Map()
  return value => {
    const cachedResult = cache.get(value)
    if (cachedResult !== undefined) return cachedResult
    const result = fn(value)
    cache.set(value, result)
    return result
  }
}
constructor(props) {
  super(props);
  this.handleClick = this.handleClick.bind(this);
}
handleClick() {
  // Perform some logic
}
handleClick = () => {
  console.log('this is:', this);
}
render() {
  return (
    <button onClick={this.handleClick}>
      Click me
    </button>
  );
}
<button onClick={e => this.handleClick(e)}>Click me</button>
const myString = "hello!"
myString.replace("!", "") // returns a new string, cannot mutate the original value
const originalArray = [1, 2, 3]
originalArray.push(4) // mutates originalArray, now [1, 2, 3, 4]
originalArray.concat(4) // returns a new array, does not mutate the original
fs.readFile(filePath, function(err, data) {
  if (err) {
    // handle the error, the return is important here
    // so execution stops here
    return console.log(err)
  }
  // use the data object
  console.log(data)
})
var isTrue = function(value, callback) {
  if (value === true) {
    callback(null, "Value was true.")
  } else {
    callback(new Error("Value is not true!"))
  }
}
var callback = function(error, retval) {
  if (error) {
    console.log(error)
    return
  }
  console.log(retval)
}
isTrue(false, callback)
isTrue(true, callback)
/*
  { stack: [Getter/Setter],
    arguments: undefined,
    type: undefined,
    message: 'Value is not true!' }
  Value was true.
*/
const person = {
  name: "John",
  age: 50,
  birthday() {
    this.age++
  }
}
person.birthday() // person.age === 51
function Person(name, age) {
  this.name = name
  this.age = age
}
Person.prototype.birthday = function() {
  this.age++
}
const person1 = new Person("John", 50)
const person2 = new Person("Sally", 20)
person1.birthday() // person1.age === 51
person2.birthday() // person2.age === 21
const createPerson = (name, age) => {
  const birthday = () => person.age++
  const person = { name, age, birthday }
  return person
}
const person = createPerson("John", 50)
person.birthday() // person.age === 51
const personProto = {
  birthday() {
    this.age++
  }
}
const person = Object.create(personProto)
person.age = 50
person.birthday() // person.age === 51
Object.create(personProto, {
  age: {
    value: 50,
    writable: true,
    enumerable: true
  }
})
function myFunction(parameter1, parameter2) {
  console.log(arguments[0]) // "argument1"
}
myFunction("argument1", "argument2")
<button onClick={() => this.handleClick(id)} />
<button onClick={this.handleClick.bind(this, id)} />
const square = v => v * v
const double = v => v * 2
const addOne = v => v + 1
const res = pipe(square, double, addOne)
res(3) // 19; addOne(double(square(3)))
const pipe = (...fns) => x => fns.reduce((v, fn) => fn(v), x)
ReactDOM.createPortal(child, container)
let i = 0
i++ // 0
// i === 1
let i = 0
++i // 1
// i === 1
new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("result")
  }, 100)
})
  .then(console.log)
  .catch(console.error)
import PropTypes from "prop-types"
class User extends React.Component {
  static propTypes = {
    name: PropTypes.string.isRequired,
    age: PropTypes.number.isRequired
  }
//
//   render() {
//     return (
//       <h1>Welcome, {this.props.name}</h1>
//       <h2>Age, {this.props.age}
//     )
//   }
// }
const a = (x, y) => x + y
const b = (arr, value) => arr.concat(value)
const c = arr => [...arr].sort((a, b) => a - b)
const a = (x, y) => x + y + Math.random()
const b = (arr, value) => (arr.push(value), arr)
const c = arr => arr.sort((a, b) => a - b)
const nest = (items, id = null, link = "parent_id") =>
  items
    .filter(item => item[link] === id)
    .map(item => ({ ...item, children: nest(items, item.id) }))
const comments = [
  { id: 1, parent_id: null, text: "First reply to post." },
  { id: 2, parent_id: 1, text: "First reply to comment #1." },
  { id: 3, parent_id: 1, text: "Second reply to comment #1." },
  { id: 4, parent_id: 3, text: "First reply to comment #3." },
  { id: 5, parent_id: 4, text: "First reply to comment #4." },
  { id: 6, parent_id: null, text: "Second reply to post." }
]
nest(comments)
/*
[
  { id: 1, parent_id: null, text: "First reply to post.", children: [...] },
  { id: 6, parent_id: null, text: "Second reply to post.", children: [] }
]
*/
const a = [1, 2, 3]
const b = [1, 2, 3]
const c = "1,2,3"
console.log(a == c)
console.log(a == b)
class MyComponent extends React.Component {
  constructor(props) {
    super(props)
    this.myRef = React.createRef()
  }
  render() {
    return <div ref={this.myRef} />
  }
}
>>>>function greet() {
  return
  {
    message: "hello"
  }
}
const previousLine = 3
;[1, 2, previousLine].map(n => n * 2)
const previousLine = 3
;(function() {
  // ...
})()
true || false
false && true
true || nonexistentFunction()
false && nonexistentFunction()
true || nonexistentFunction() || window.nothing.wouldThrowError
true || window.nothing.wouldThrowError
true
const options = {}
const setting = options.setting || "default"
setting // "default"
// Instead of:
addEventListener("click", e => {
  if (e.target.closest("button")) {
    handleButtonClick(e)
  }
})
// You can take advantage of short-circuit evaluation:
addEventListener(
  "click",
  e => e.target.closest("button") && handleButtonClick(e)
)
// Stateful class component
class App extends Component {
  constructor(props) {
    super(props)
    this.state = { count: 0 }
  }
  render() {
    // ...
  }
}
// Stateful function component
function App() {
  const [count, setCount] = useState(0)
  return // ...
}
Array.isArray // static method of Array
Array.prototype.push // instance method of Array
const arr = [1, 2, 3]
arr.push(4)
Array.push(arr, 4)
var myObject = {
  property: this,
  regularFunction: function() {
    return this
  },
  arrowFunction: () => {
    return this
  },
  iife: (function() {
    return this
  })()
}
myObject.regularFunction() // myObject
myObject["regularFunction"]() // my Object
myObject.property // NOT myObject; lexical `this`
myObject.arrowFunction() // NOT myObject; lexical `this`
myObject.iife // NOT myObject; lexical `this`
const regularFunction = myObject.regularFunction
regularFunction() // NOT myObject; lexical `this`
document.body.addEventListener("click", function() {
  console.log(this) // document.body
})
class Example {
  constructor() {
    console.log(this) // myExample
  }
}
const myExample = new Example()
var myFunction = function() {
  return this
}
myFunction.call({ customThis: true }) // { customThis: true }
var obj = {
  arr: [1, 2, 3],
  doubleArr() {
    return this.arr.map(function(value) {
      // this is now this.arr
      return this.double(value)
    })
  },
  double() {
    return value * 2
  }
}
obj.doubleArr() // Uncaught TypeError: this.double is not a function
typeof typeof 0
for (var i = 0; i < 10; i++) {
  setTimeout(() => {
    // logs `10` ten times
    console.log(i)
  })
}
/* Solutions with `var` */
for (var i = 0; i < 10; i++) {
  // Passed as an argument will use the value as-is in
  // that point in time
  setTimeout(console.log, 0, i)
}
for (var i = 0; i < 10; i++) {
  // Create a new function scope that will use the value
  // as-is in that point in time
  ;(i => {
    setTimeout(() => {
      console.log(i)
    })
  })(i)
}
for (let i = 0; i < 10; i++) {
  setTimeout(() => {
    // logs 0, 1, 2, 3, ...
    console.log(i)
  })
}
const myObject = {}
myObject.prop = "hello!" // No error
myObject = "hello" // Error