├── static
├── robots.txt
├── favicon.ico
└── js-quiz.jpeg
├── .prettierignore
├── typeOfNaN-logo.jpg
├── .prettierrc
├── src
├── pages
│ ├── index.css
│ ├── 404.js
│ └── index.js
├── templates
│ ├── correct.png
│ ├── incorrect.png
│ └── question.js
├── components
│ ├── bio.css
│ ├── learn-more.js
│ ├── bio.js
│ ├── modal.js
│ ├── seo.js
│ └── layout.js
└── utils
│ ├── gaAnswerTracking.js
│ ├── typography.js
│ ├── persistAnswers.js
│ ├── shouldRenderContributor.js
│ └── filterPosts.js
├── content
├── assets
│ └── gatsby-icon.png
└── questions
│ ├── console-log-constructors
│ └── index.md
│ ├── Array_Object
│ └── index.md
│ ├── Array-Method-findIndex
│ └── index.md
│ ├── combining-different-types
│ └── index.md
│ ├── comma-operator
│ └── index.md
│ ├── object-property-equality
│ └── index.md
│ ├── object-prop-mutation
│ └── index.md
│ ├── map-letters-to-numbers
│ └── index.md
│ ├── string-methods
│ └── index.md
│ ├── flattened-array
│ └── index.md
│ ├── console-log-fetch
│ └── index.md
│ ├── pick-the-rotten-bean-in-an-array
│ └── index.md
│ ├── iffe-hof-both
│ └── index.md
│ ├── palindrome
│ └── index.md
│ ├── set-uniqueness-ordering
│ └── index.md
│ ├── function-function-syntax
│ └── index.md
│ ├── array-loop-largest-number
│ └── index.md
│ ├── equality-operators
│ └── index.md
│ ├── implicit-semicolon-behavior
│ └── index.md
│ ├── equality-operators-compare
│ └── index.md
│ ├── global-local-scopes
│ └── index.md
│ ├── short-circuit-notifications
│ └── index.md
│ ├── the-walking-dead
│ └── index.md
│ ├── function-argument-mutation
│ └── index.md
│ ├── merge-two-arrays
│ └── index.md
│ ├── object-keys-object-values
│ └── index.md
│ ├── reduce-math
│ └── index.md
│ ├── spread-and-rename
│ └── index.md
│ ├── template-literals
│ └── index.md
│ ├── array-method-binding
│ └── index.md
│ ├── a-set-of-objects
│ └── index.md
│ ├── basic-recursion
│ └── index.md
│ ├── array-pop
│ └── index.md
│ ├── promise-all-resolve-order
│ └── index.md
│ ├── batman-v-superman
│ └── index.md
│ ├── function-equality
│ └── index.md
│ ├── identity-crisis
│ └── index.md
│ ├── floating-point-precision
│ └── index.md
│ ├── array-method-callbacks
│ └── index.md
│ ├── prototypal-inheritance
│ └── index.md
│ ├── string-interpolation
│ └── index.md
│ ├── type-coercion
│ └── index.md
│ ├── arrow-functions
│ └── index.md
│ ├── delete-object-properties
│ └── index.md
│ ├── confusing-date
│ └── index.md
│ ├── array-as-boolean
│ └── index.md
│ ├── object-clone-stringify-mutation
│ └── index.md
│ ├── array-object-efficiency
│ └── index.md
│ ├── deep-object-mutability
│ └── index.md
│ ├── event-scheduling
│ └── index.md
│ ├── callback-set-timeout
│ └── index.md
│ ├── off-to-the-races
│ └── index.md
│ ├── array-compare-2
│ └── index.md
│ ├── array-compare
│ └── index.md
│ ├── array-method-slice
│ └── index.md
│ ├── inceptionloop
│ └── index.md
│ ├── array-sort-comparison
│ └── index.md
│ ├── pass-by-value
│ └── index.md
│ ├── digit-with-dots-in-js
│ └── index.md
│ ├── operator-associativity
│ └── index.md
│ ├── triple-plus
│ └── index.md
│ ├── async-await
│ └── index.md
│ ├── lexical-scope
│ └── index.md
│ ├── copying-arrays
│ └── index.md
│ ├── reduce-object
│ └── index.md
│ ├── object-clone-assign-mutation
│ └── index.md
│ ├── object-clone-stringify
│ └── index.md
│ ├── implicit-semicolon
│ └── index.md
│ ├── this-keyword
│ └── index.md
│ ├── hoisting-race-to-the-top
│ └── index.md
│ ├── array-length-alias-default-value
│ └── index.md
│ ├── arrays-sorting-reversing
│ └── index.md
│ ├── closure-and-hoisting
│ └── index.md
│ ├── curly-q
│ └── index.md
│ └── typeof-nan
│ └── index.md
├── gatsby-browser.js
├── scripts
└── new-question
│ ├── index.md
│ └── index.js
├── .github
└── ISSUE_TEMPLATE
│ ├── question-request.md
│ ├── feature_request.md
│ └── bug_report.md
├── CONTRIBUTING.md
├── LICENSE
├── gatsby-node.js
├── package.json
├── README.md
├── .gitignore
├── CODE_OF_CONDUCT.md
└── gatsby-config.js
/static/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow:
3 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | .cache
2 | package.json
3 | package-lock.json
4 | public
5 |
--------------------------------------------------------------------------------
/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nas5w/typeofnan-javascript-quizzes/HEAD/static/favicon.ico
--------------------------------------------------------------------------------
/static/js-quiz.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nas5w/typeofnan-javascript-quizzes/HEAD/static/js-quiz.jpeg
--------------------------------------------------------------------------------
/typeOfNaN-logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nas5w/typeofnan-javascript-quizzes/HEAD/typeOfNaN-logo.jpg
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": true,
3 | "singleQuote": true,
4 | "tabWidth": 2,
5 | "printWidth": 60
6 | }
7 |
--------------------------------------------------------------------------------
/src/pages/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-size: 20px;
3 | }
4 |
5 | #filter-questions {
6 | margin-bottom: 1rem;
7 | }
8 |
--------------------------------------------------------------------------------
/src/templates/correct.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nas5w/typeofnan-javascript-quizzes/HEAD/src/templates/correct.png
--------------------------------------------------------------------------------
/src/templates/incorrect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nas5w/typeofnan-javascript-quizzes/HEAD/src/templates/incorrect.png
--------------------------------------------------------------------------------
/content/assets/gatsby-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nas5w/typeofnan-javascript-quizzes/HEAD/content/assets/gatsby-icon.png
--------------------------------------------------------------------------------
/gatsby-browser.js:
--------------------------------------------------------------------------------
1 | // custom typefaces
2 | import 'typeface-montserrat';
3 | import 'typeface-merriweather';
4 | import 'prism-themes/themes/prism-base16-ateliersulphurpool.light.css';
5 |
--------------------------------------------------------------------------------
/src/components/bio.css:
--------------------------------------------------------------------------------
1 | .button-link {
2 | background-color: transparent;
3 | border: 0;
4 | color: #4183c4;
5 | }
6 |
7 | .button-link:hover {
8 | color: #1e70bf;
9 | }
10 |
--------------------------------------------------------------------------------
/scripts/new-question/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title:
3 | tags:
4 | -
5 | order: <%= order %>
6 | date: <%= date %>
7 | answers:
8 | -
9 | ---
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/question-request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Question request
3 | about: Request a question be added to the app
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | # Topic
11 |
12 | Describe the question topic
13 |
14 | # Proposed Content
15 |
16 | Add proposed example or content here if you have any
17 |
18 | # Other Notes
19 |
20 | Anything else we should know?
21 |
--------------------------------------------------------------------------------
/src/utils/gaAnswerTracking.js:
--------------------------------------------------------------------------------
1 | export const gaTrackAnswer = (title, answer, correct) => {
2 | if (window.ga) {
3 | window.ga('send', {
4 | hitType: 'event',
5 | eventCategory: 'SubmitAnswer',
6 | eventAction: 'click',
7 | eventLabel: title,
8 | eventValue: answer === correct ? 1 : 0
9 | });
10 | } else {
11 | console.error('ga unavailable');
12 | }
13 | };
14 |
--------------------------------------------------------------------------------
/src/utils/typography.js:
--------------------------------------------------------------------------------
1 | import Typography from "typography"
2 | import Wordpress2016 from "typography-theme-wordpress-2016"
3 |
4 | Wordpress2016.overrideThemeStyles = () => {
5 | return {
6 | "a.gatsby-resp-image-link": {
7 | boxShadow: `none`,
8 | },
9 | }
10 | }
11 |
12 | delete Wordpress2016.googleFonts
13 |
14 | const typography = new Typography(Wordpress2016)
15 |
16 | // Hot reload typography in development.
17 | if (process.env.NODE_ENV !== `production`) {
18 | typography.injectStyles()
19 | }
20 |
21 | export default typography
22 | export const rhythm = typography.rhythm
23 | export const scale = typography.scale
24 |
--------------------------------------------------------------------------------
/content/questions/console-log-constructors/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Console Log Constructors
3 | tags:
4 | - array
5 | - object
6 | order: 38
7 | date: '2019-09-19'
8 | answers:
9 | - 'object array number'
10 | - 'object object number'
11 | - 'object object object'
12 | - 'something else // correct'
13 | ---
14 |
15 | Consider the following code block. What gets logged?
16 |
17 | ```javascript
18 | console.log(
19 | typeof Object,
20 | typeof Array,
21 | typeof Number
22 | );
23 | ```
24 |
25 |
26 |
27 | The correct answer is 'function function function' - Object, Array and Number are all constructors (functions).
28 |
--------------------------------------------------------------------------------
/content/questions/Array_Object/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Array Object Iteration
3 | tags:
4 | - Array
5 | - Objects
6 | - Element
7 | order: 56
8 | date: Sun Oct 20 2019 14:33:16 GMT-0700 (Pacific Daylight Time)
9 | answers:
10 | - forEach() // correct
11 | - every()
12 | - concat()
13 | ---
14 |
15 | Which of the following array methods is guaranteed to iterate through each element of an array?
16 |
17 |
18 |
19 | `forEach()` calls a provided callback function once for each element in an array in ascending order. `every()` will stop as soon as the provided function results in a falsey condition. `concat()` simply combines two arrays.
20 |
--------------------------------------------------------------------------------
/content/questions/Array-Method-findIndex/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: array.findIndex
3 | tags:
4 | - array
5 | order: 58
6 | date: Tue Oct 22 2019 14:22:21 GMT-0600 (Mountain Daylight Time)
7 | answers:
8 | - 'True'
9 | - 'False // correct'
10 | ---
11 |
12 | True or False: `array.findIndex` will return 0 when no elements pass the test.
13 |
14 |
15 | `findIndex` will actually return a `-1` since `0` would be a legitimate array index!
16 |
17 | Under the hood, this array method executes a callback function for each index until a truthy value is returned. If the array length is 0 or if the callback never returns a truthy value then findIndex will return -1.
18 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/content/questions/combining-different-types/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Combining Different Types
3 | tags:
4 | - types
5 | order: 31
6 | date: '2019-10-05'
7 | answers:
8 | - '3 1'
9 | - '"21" 1 // correct'
10 | - '"21" ""'
11 | - 'An error is thrown'
12 | ---
13 |
14 | What gets logged in the following scenario?
15 |
16 | ```javascript
17 | console.log(2 + "1");
18 | console.log(2 - "1");
19 | ```
20 |
21 |
22 |
23 | The first expression evaluates to `"21"` because the `+` operator results in string concatenation when either operand is a string. On the other hand, the `-` operator cannot act on strings so `"1"` gets converted to a number in the evaluation of the second expression.
24 |
--------------------------------------------------------------------------------
/content/questions/comma-operator/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Comma Operator
3 | tags:
4 | - operator
5 | order: 72
6 | date: Sat May 02 2020 18:45:16 GMT+0700 (Indochina Time)
7 | answers:
8 | - '6'
9 | - '27 // correct'
10 | - '15'
11 | - '28'
12 | ---
13 |
14 | Consider the following code block. What gets logged?
15 |
16 | ```javascript
17 | let x = 5;
18 | function addFive(num) {
19 | return num + 5;
20 | }
21 | x = (x++ , x = addFive(x), x *= 2, x -= 5, x += 10);
22 | console.log(x)
23 | ```
24 |
25 |
26 |
27 | The comma operator (,) evaluates each of its operands (from left to right) and returns the value of the last operand. The result = (((6 + 5) * 2) - 5) + 10 = 27.
28 |
29 |
--------------------------------------------------------------------------------
/content/questions/object-property-equality/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Object Property Equality
3 | tags:
4 | - object
5 | - property
6 | order: 18
7 | date: '2019-09-29'
8 | answers:
9 | - 'true // correct'
10 | - 'false'
11 | ---
12 |
13 | `a` and `b` are different objects with the same `firstName` property. Are these properties strictly equal to each other?
14 |
15 | ```javascript
16 | const a = {
17 | firstName: 'Bill'
18 | };
19 |
20 | const b = {
21 | firstName: 'Bill'
22 | };
23 |
24 | console.log(a.firstName === b.firstName);
25 | ```
26 |
27 |
28 |
29 | The answer is yes, they are. `a.firstName` is the string value `Bill` and `b.firstName` is the string value `Bill`. Two identical strings are always equal.
30 |
--------------------------------------------------------------------------------
/content/questions/object-prop-mutation/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Object Property Mutation
3 | tags:
4 | - object
5 | - mutation
6 | order: 21
7 | date: '2019-09-29'
8 | answers:
9 | - '{ firstName: "Joe" }'
10 | - '{ firstName: "Pete" } // correct'
11 | ---
12 |
13 | Consider objects `a` and `b` below. What gets logged?
14 |
15 | ```javascript
16 | const a = { firstName: 'Joe' };
17 | const b = a;
18 | b.firstName = 'Pete';
19 | console.log(a);
20 | ```
21 |
22 |
23 |
24 | When we set `b = a` in the second line, `b` and `a` are pointing to the same object in memory. Changing the `firstName` property on `b` will therefore change the `firstName` property on the only object in memory, so `a.firstName` will reflect this change.
25 |
--------------------------------------------------------------------------------
/content/questions/map-letters-to-numbers/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Map letters to numbers
3 | tags:
4 | - array
5 | - map
6 | order: 24
7 | date: '2019-10-01'
8 | answers:
9 | - '1, 2, 3'
10 | - 'a, b, c'
11 | - '[1, 2, 3] // correct'
12 | - '[a, b, c]'
13 | ---
14 |
15 | Consider the following mapping. What gets logged?
16 |
17 | ```javascript
18 | const myArr = ['a', 'b', 'c'];
19 | const myMap = { a: 1, b: 2, c: 3 };
20 |
21 | const result = myArr.map(letter => myMap[letter]);
22 | console.log(result);
23 | ```
24 |
25 |
26 |
27 | The `map` method will create a new array from an existing array by performing a specified transformation on each array item. In this example, each letter is replaced by a corresponding object's value.
28 |
--------------------------------------------------------------------------------
/content/questions/string-methods/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: String Methods
3 | tags:
4 | - String methods
5 | order: 34
6 | date: '2019-10-06'
7 | answers:
8 | - 'length'
9 | - 'indexOf // correct'
10 | - 'find'
11 | - 'none'
12 | ---
13 |
14 | String methods are used to work with string in JavaScript. Which method would be used to find a specified value and return the position of the match?
15 |
16 | For example, what method would tell you that `"bird"` is at position `4` in the following `word` string?
17 |
18 | ```javascript
19 | const word = 'The bird is the word';
20 | ```
21 |
22 |
23 |
24 | The `indexOf` method searches a string for a specified value and returns the position of the match. In this example, `word.indexOf("bird")` will equal `4`.
25 |
--------------------------------------------------------------------------------
/content/questions/flattened-array/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Using Array#flat
3 | tags:
4 | - array
5 | - es2019
6 | - flat
7 | order: 47
8 | date: '2019-10-10'
9 | answers:
10 | - '[1, 2, 3, 4, 5, 6, [7], 8, 9, 10, 12] // correct'
11 | - '[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12]'
12 | ---
13 |
14 | Consider the following nested array. What will get logged?
15 |
16 | ```javascript
17 | const array = [1,[2,[3,[4,[5,[6,[7],8],9],10]]],12];
18 | const result = array.flat(5);
19 | console.log(result);
20 | ```
21 |
22 |
23 |
24 | The `Array#flat` introduced in ES2019 will flatten an array up to the given depth level. If the depth is unknown, `Infinity` can be passed. If no depth is provided, the default depth will be 1. Passing 0 will return the array without modification.
25 |
--------------------------------------------------------------------------------
/content/questions/console-log-fetch/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Console Log Fetch
3 | tags:
4 | - fetch
5 | order: 6
6 | date: '2019-09-27'
7 | answers:
8 | - 'The fetch function'
9 | - 'A reference error'
10 | - 'It depends on the environment you are in // correct'
11 | ---
12 |
13 | What gets logged when I try to log `fetch`?
14 |
15 | ```javascript
16 | console.log(fetch);
17 | ```
18 |
19 |
20 |
21 | What happens when you `console.log(fetch)` really depends on your current environment. If you `console.log` it in a [browser version](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API#Browser_compatibility) that has a `window.fetch` method, you will log the fetch function. If you have an older browser, or are not in a browser environment, you will receive a ReferenceError.
22 |
--------------------------------------------------------------------------------
/content/questions/pick-the-rotten-bean-in-an-array/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Pick the Rotten Bean in an Array
3 | tags:
4 | - array
5 | order: 54
6 | date: '2019-10-20'
7 | answers:
8 | - 'A // correct'
9 | - 'B'
10 | - 'Both of them'
11 | ---
12 |
13 | There is a rotten bean which looks different inside a basket. Which option below is the right way to create a new array containing only the rotten bean?
14 |
15 | ```javascript
16 | var basket = [0, 0, 0, 0, 9];
17 |
18 | // A
19 | basket.splice(4, 1);
20 |
21 | // B
22 | basket.slice(4, 1);
23 | ```
24 |
25 |
26 |
27 | Option B in this case is not the right choice: the optional second parameter of the `slice` method must be the end index of the portion of the array you want to slice. (It's not the number of elements you want to delete.)
28 |
--------------------------------------------------------------------------------
/src/pages/404.js:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { graphql } from "gatsby"
3 |
4 | import Layout from "../components/layout"
5 | import SEO from "../components/seo"
6 |
7 | class NotFoundPage extends React.Component {
8 | render() {
9 | const { data } = this.props
10 | const siteTitle = data.site.siteMetadata.title
11 |
12 | return (
13 |
14 |
15 |
Not Found
16 |
You just hit a route that doesn't exist... the sadness.
17 |
18 | )
19 | }
20 | }
21 |
22 | export default NotFoundPage
23 |
24 | export const pageQuery = graphql`
25 | query {
26 | site {
27 | siteMetadata {
28 | title
29 | }
30 | }
31 | }
32 | `
33 |
--------------------------------------------------------------------------------
/content/questions/iffe-hof-both/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: IIFE, HOF, or Both
3 | tags:
4 | - iife
5 | - hof
6 | order: 13
7 | date: '2019-09-29'
8 | answers:
9 | - 'IIFE only'
10 | - 'HOF only'
11 | - 'Both IIFE and HOF // correct'
12 | - 'Neither'
13 | ---
14 |
15 | Does the following snippet illustrate an Immediately-Invoked Function Expression (IIFE), a Higher-Order Function (HOF), both, or neither?
16 |
17 | ```javascript
18 | ((fn, val) => {
19 | return fn(val);
20 | })(console.log, 5);
21 | ```
22 |
23 |
24 |
25 | The snippet clearly illustates an IIFE as we immediately invoke a function by passing `console.log` and `5` to it. Additionally, we find that this is a HOF as `fn` is a function, and a HOF is defined as any function that takes another function as a parameter or returns a function.
26 |
--------------------------------------------------------------------------------
/content/questions/palindrome/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Palindrome?
3 | tags:
4 | - "string methods"
5 | order: 58
6 | date: Sun Oct 20 2019 15:23:46 GMT-0700 (Pacific Daylight Time)
7 | answers:
8 | - 'true // correct'
9 | - 'false'
10 | ---
11 |
12 | Does the following function correctly assess 'hannah' to be a palindrome? In other words, what gets logged?
13 |
14 | ```javascript
15 | function isPalindrome(str){
16 | var reverseText = str.split('').reverse().join('');
17 | return str == reverseText;
18 | }
19 |
20 | isPalindrome('hannah');
21 | ```
22 |
23 |
24 |
25 | `split('')` will split the string into an array of letters, `reverse()` will reverse that array, and `join('')` will join the letters back together. If that reversed text is equal to the initial string, then we indeed know we have a palindrome!
26 |
--------------------------------------------------------------------------------
/content/questions/set-uniqueness-ordering/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Set Uniqueness and Ordering
3 | tags:
4 | - Set
5 | - spread
6 | order: 12
7 | date: '2019-09-29'
8 | answers:
9 | - '5 2'
10 | - '5 3'
11 | - '4 2 // correct'
12 | - '4 3'
13 | ---
14 |
15 | In the following problem, we use the `Set` object and spread syntax to create a new array. What gets logged (to consider: Are items forced to be unique? Are they sorted?)
16 |
17 | ```javascript
18 | const arr = [...new Set([3, 1, 2, 3, 4])];
19 | console.log(arr.length, arr[2]);
20 | ```
21 |
22 |
23 |
24 | The `Set` object will force unique elements (duplicate elements already in the set are ignored), but will not change order. The resultant `arr` array will be `[3, 1, 2, 4]`, meaning `arr.length` is `4` and `arr[2]` (the third element of the array) is `2`.
25 |
--------------------------------------------------------------------------------
/content/questions/function-function-syntax/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Function Function Syntax
3 | tags:
4 | - function
5 | - hof
6 | order: 20
7 | date: '2019-09-29'
8 | answers:
9 | - 'Yes // correct'
10 | - 'No'
11 | ---
12 |
13 | Let's say `myFunc` is a function, `val1` is a variable, and `val2` is a variable. Is the following syntax allowed in JavaScript?
14 |
15 | ```javascript
16 | myFunc(val1)(val2);
17 | ```
18 |
19 |
20 |
21 | This is a common pattern for a higher-order function. If `myFunc(val1)` returns a function, then that function will be called with `val2` as an argument. Here's an example of this in action that you can try out:
22 |
23 | ```javascript
24 | const timesTable = num1 => {
25 | return num2 => {
26 | return num1 * num2;
27 | };
28 | };
29 |
30 | console.log(timesTable(4)(5));
31 | // 20
32 | ```
33 |
--------------------------------------------------------------------------------
/content/questions/array-loop-largest-number/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Greatest Number in an Array
3 | tags:
4 | - function
5 | - array
6 | - loop
7 | order: 22
8 | date: '2019-10-01'
9 | answers:
10 | - 'Yes'
11 | - 'No // correct'
12 | ---
13 |
14 | Will the following function always return the greatest number in an array?
15 |
16 | ```javascript
17 | function greatestNumberInArray(arr) {
18 | let greatest = 0;
19 | for (let i = 0; i < arr.length; i++) {
20 | if (greatest < arr[i]) {
21 | greatest = arr[i];
22 | }
23 | }
24 | return greatest;
25 | }
26 | ```
27 |
28 |
29 |
30 | This function will work fine for arrays where at least one value is `0` or greater; however, it will fail if all numbers are below `0`. This is because the `greatest` variable starts at `0` even if `0` is greater than all array elements.
31 |
--------------------------------------------------------------------------------
/content/questions/equality-operators/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Equality and Identity Operators
3 | tags:
4 | - operators
5 | order: 57
6 | date: Sun Oct 20 2019 12:14:42 GMT-0700 (Pacific Daylight Time)
7 | answers:
8 | - 'true, false // correct'
9 | - 'true, true'
10 | - 'false, true'
11 | - 'false, false'
12 | ---
13 |
14 | Consider the following equality comparison. What gets logged?
15 |
16 | ```javascript
17 | var x = 5;
18 | var y = "5";
19 |
20 | console.log(x == y);
21 | console.log(x === y);
22 | ```
23 |
24 |
25 |
26 | The equality operator `==` first converts operands to the same types before doing a strict comparison, so that's why `x == y` logs `true`. The identity operator "===" *only* carries out a strict comparision; there is no type conversion. `x === y` therefore returns `false` because `x` and `y` do not share the same type.
27 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | You are invited to contribute to this repository! You can do so by opening an issue, or by directly contributing questions.
4 |
5 | To directly contribute a quiz question, do the following:
6 |
7 | - Fork the repository fork_and_knife
8 | - Add a new folder under `content/questions/`. This folder name will become the questions route in the application (for example, a folder named `foo-bar` will be accessible at https://quiz.typeofnan.dev/foo-bar)
9 | - Add an `index.md` file in the new folder.
10 | - Follow the patterns used in other questions in content/questions
11 | - If you have any questions, let me know in the issues section or via [Twitter](https://twitter.com/nas5w)
12 |
13 | As you contribute, please keep the [Code of Conduct](./CODE_OF_CONDUCT.md) in mind and treat your fellow contributors with care and empathy!
14 |
15 | Thank you!
16 |
--------------------------------------------------------------------------------
/content/questions/implicit-semicolon-behavior/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Implicit semicolon behavior
3 | tags:
4 | - semicolon
5 | - implicit
6 | - print
7 | order: 73
8 | date: Mon, 27 Jan 2020 17:28:48 GMT
9 | answers:
10 | - '[1, 2]'
11 | - '[1, 2, 3]'
12 | - 'ReferenceError // correct'
13 | ---
14 |
15 | What does this snippet of code print?
16 |
17 | ```javascript
18 | let array = [1, 2]
19 |
20 | (array).push(3)
21 |
22 | console.log(array)
23 | ```
24 |
25 |
26 |
27 | Javascript would normally add a semicolon after the `let
28 | array` line, however `(array)` is seen as calling a function
29 | and javascript actually reads `let array = [1, 2](array).push(3)`.
30 |
31 | There is a ReferenceError because the variable `array` is used
32 | inside its definition. If it used var instead, javascript would
33 | attempt to call `[1, 2]` which is a TypeError.
34 |
--------------------------------------------------------------------------------
/src/utils/persistAnswers.js:
--------------------------------------------------------------------------------
1 | export const persistAnswer = (
2 | title,
3 | selectedAnswer,
4 | correctAnswer
5 | ) => {
6 | typeof window !== 'undefined' &&
7 | localStorage.setItem(
8 | title,
9 | JSON.stringify({ selectedAnswer, correctAnswer })
10 | );
11 | };
12 |
13 | export const getPersistedAnswer = title => {
14 | const item =
15 | typeof window !== 'undefined' &&
16 | localStorage.getItem(title);
17 | if (!item) {
18 | return { selectedAnswer: null, correctAnswer: null };
19 | }
20 | return JSON.parse(item);
21 | };
22 |
23 | export const clearPersistedAnswer = title => {
24 | typeof window !== 'undefined' &&
25 | localStorage.removeItem(title);
26 | };
27 |
28 | export const clearAllPersistedAnswer = () => {
29 | typeof window !== 'undefined' &&
30 | localStorage.clear();
31 | };
--------------------------------------------------------------------------------
/content/questions/equality-operators-compare/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Equality and Identity Operators
3 | tags:
4 | - operator
5 | - property
6 | order: 34
7 | date: '2019-10-5'
8 | answers:
9 | - 'true'
10 | - 'false // correct'
11 | ---
12 |
13 | `a` and `b` are two constants. What will be the output on the console?
14 |
15 | ```javascript
16 | const a = '42';
17 | const b = 42;
18 |
19 | console.log((a == b) && (a === b));
20 | ```
21 |
22 |
23 |
24 | The answer is `false`. `a == b` uses the "equality" operator, which will convert the operands to the same type prior to performing the comparison. In this case, `42 == '42'` will become `42 === 42`, which is `true`.
25 |
26 | However, `a === b` uses the "identity" operator, and no such type conversion happens. Therefore, `42 === '42'` is `false`. Hence, `(a == b) && (a === b)` becomes `true && false`, which is `false`.
27 |
--------------------------------------------------------------------------------
/content/questions/global-local-scopes/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Global Local
3 | tags:
4 | - variables
5 | - scope
6 | - hoisting
7 | order: 37
8 | date: '2019-10-06'
9 | answers:
10 | - 5 and 10
11 | - undefined and 10 // correct
12 | - 5 and undefined
13 | - undefined and undefined
14 | ---
15 |
16 | Consider the following code block. What gets logged?
17 |
18 | ```javascript
19 | var x = 5;
20 |
21 | (function() {
22 | console.log(x);
23 | var x = 10;
24 | console.log(x);
25 | })();
26 | ```
27 |
28 |
29 |
30 | This will print out `undefined` and `10`. JavaScript will hoist the `var x` to the top of the function (or top level), but it will not hoist the assignment. The code is equivalent to:
31 |
32 | ```javascript
33 | var x;
34 | x = 5;
35 |
36 | (function() {
37 | var x;
38 | console.log(x);
39 | x = 10;
40 | console.log(x);
41 | })();
42 | ```
43 |
--------------------------------------------------------------------------------
/content/questions/short-circuit-notifications/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Short-Circuit Notification(s)
3 | tags:
4 | - short-circuit
5 | order: 9
6 | date: '2019-09-27'
7 | answers:
8 | - 'You have 1 notification'
9 | - 'You have 1 notifications'
10 | - 'Something else // correct'
11 | ---
12 |
13 | Let's display some notifications to our user! What gets logged in the following snippet?
14 |
15 | ```javascript
16 | const notifications = 1;
17 |
18 | console.log(
19 | `You have ${notifications} notification${notifications !==
20 | 1 && 's'}`
21 | );
22 | ```
23 |
24 |
25 |
26 | Unfortunately, our short-circuit evaluation will not work as intended here: `notifications !== 1 && 's'` evaluates to `false`, meaning we will actually be logging `You have 1 notificationfalse`. If we want our snippet to work correctly, we could consider the conditional operator: `${notifications === 1 ? '' : 's'}`.
27 |
--------------------------------------------------------------------------------
/content/questions/the-walking-dead/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: The Walking Dead
3 | tags:
4 | - objects
5 | - delete keywords
6 | - Type systems
7 | order: 35
8 | date: '2019-10-06'
9 | answers:
10 | - '1'
11 | - 'An error is thrown'
12 | - 'undefined // correct'
13 | - 'Something different is logged'
14 | ---
15 |
16 | What is the output of the following `console.log`?
17 |
18 | ```javascript
19 | const a = { something: 1, someOtherThing: 2 };
20 |
21 | const deleteSomething = input => {
22 | delete input.something;
23 | return input.something;
24 | };
25 |
26 | const result = deleteSomething(a);
27 |
28 | console.log(result);
29 | ```
30 |
31 |
32 |
33 | The output will be `undefined` because the `delete` operator has already deleted the property `something` before we attempted to return it. When we try to access a non-existent object property, it will always return the value `undefined`.
34 |
--------------------------------------------------------------------------------
/content/questions/function-argument-mutation/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Function Argument Mutation
3 | tags:
4 | - functions
5 | - mutability
6 | order: 23
7 | date: '2019-10-01'
8 | answers:
9 | - 'true // correct'
10 | - 'undefined'
11 | ---
12 |
13 | When passing an object as an argument to a function, can the orginal object be mutated? In the following example, will `somePerson.valid` be `true` or `undefined`?
14 |
15 | ```javascript
16 | const somePerson = { username: 'Davey154' };
17 |
18 | const personValidator = person => {
19 | person.valid = person.username.length > 5;
20 | return person.valid;
21 | };
22 |
23 | personValidator(somePerson);
24 |
25 | console.log(somePerson.valid); // ??
26 | ```
27 |
28 |
29 |
30 | In our function, `person` will point to the same object in memory that `somePerson` points to. This means any mutation we do to `person` within our function also happens to `somePerson`!
31 |
--------------------------------------------------------------------------------
/content/questions/merge-two-arrays/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Merge Two Arrays
3 | tags:
4 | - array
5 | order: 51
6 | date: '2019-10-12'
7 | answers:
8 | - 'A'
9 | - 'B'
10 | - 'C // correct'
11 | - 'All of them'
12 | ---
13 |
14 | Consider two arrays `a` and `b` below. Which option below is **NOT** correct to merge the arrays?
15 |
16 | ```javascript
17 | var a = [1,2,3];
18 | var b = [4,5,6];
19 |
20 | // A
21 | console.log(a.concat(b));
22 |
23 | // B
24 | console.log([...a, ...b]);
25 |
26 | // C
27 | console.log(a + b);
28 | ```
29 |
30 |
31 |
32 | Option C does not properly merge the arrays, because the arithmetic operator `+` only sensibly applies to strings and numbers. Any side of a `+` which refers to something other than a string or number will be converted into a string first, so this would result in the string `'1,2,3'` being concatenated with the string `'4,5,6'`, or `'1,2,34,5,6'`.
33 |
--------------------------------------------------------------------------------
/content/questions/object-keys-object-values/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Object Keys, Object Values
3 | tags:
4 | - object
5 | - object.keys
6 | - object.values
7 | order: 16
8 | date: '2019-09-29'
9 | answers:
10 | - 'true'
11 | - 'false // correct'
12 | ---
13 |
14 | Consider the following object.
15 |
16 | ```javascript
17 | const obj = {
18 | 1: 1,
19 | 2: 2,
20 | 3: 3
21 | };
22 | ```
23 |
24 | Is `Object.keys` equal to `Object.values`?
25 |
26 | ```javascript
27 | console.log(Object.keys(obj) == Object.values(obj));
28 | ```
29 |
30 |
31 |
32 | In this case, `Object.keys` converts the keys to be string `["1", "2", "3"]` and `Object.values` gives `[1, 2, 3]`. Even if the values turn out to be the same type, the two arrays are both different objects in memory, so the equality comparison will return `false`. You will see a lot of quiz questions here drilling into the concepts of object and array comparison!
33 |
--------------------------------------------------------------------------------
/content/questions/reduce-math/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Reduce Math
3 | tags:
4 | - reduce
5 | - array
6 | order: 8
7 | date: '2019-09-27'
8 | answers:
9 | - '1'
10 | - '60'
11 | - '100'
12 | - '120 // correct'
13 | ---
14 |
15 | Math time! What gets logged?
16 |
17 | ```javascript
18 | const arr = [
19 | x => x * 1,
20 | x => x * 2,
21 | x => x * 3,
22 | x => x * 4
23 | ];
24 |
25 | console.log(arr.reduce((agg, el) => agg + el(agg), 1));
26 | ```
27 |
28 |
29 |
30 | With `Array#reduce`, the initial value of the aggregator (here, named `agg`) is given in the second argument. In this case, that's `1`. We can then iterate over our functions as follows:
31 |
32 | 1 + 1 \* 1 = 2 (value of aggregator in next iteration)
33 | 2 + 2 \* 2 = 6 (value of aggregator in next iteration)
34 | 6 + 6 \* 3 = 24 (value of aggregator in next iteration)
35 | 24 + 24 \* 4 = 120 (final value)
36 |
37 | So, 120 it is!
38 |
--------------------------------------------------------------------------------
/content/questions/spread-and-rename/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Spread and Rename
3 | tags:
4 | - spread
5 | - array
6 | - object
7 | order: 10
8 | date: '2019-09-27'
9 | answers:
10 | - '[{ firstName: "James" }]'
11 | - '[{ firstName: "Jonah" }] // correct'
12 | - 'Something else'
13 | ---
14 |
15 | Consider the following array with a single object. What happens when we spread that array and change the `firstName` property on the 0-index object?
16 |
17 | ```javascript
18 | const arr1 = [{ firstName: 'James' }];
19 | const arr2 = [...arr1];
20 | arr2[0].firstName = 'Jonah';
21 |
22 | console.log(arr1);
23 | ```
24 |
25 |
26 |
27 | Spread creates a shallow copy of the array, meaning the object contained in `arr2` is still pointing to the same object in memory that the `arr1` object is pointing to. So, changing the `firstName` property of the object in one array will be reflected by the object in the other array changing as well.
28 |
--------------------------------------------------------------------------------
/content/questions/template-literals/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Template Literals
3 | tags:
4 | - compiling
5 | - scripting
6 | - ie11
7 | - babel
8 | order: 53
9 | date: Sat Oct 12 2019 17:08:35 GMT-0400 (Eastern Daylight Time)
10 | answers:
11 | - ecmascript
12 | - es2015 // correct
13 | - stage-6
14 | ---
15 |
16 | Which JavaScript language version supports template literals syntax, like below?
17 |
18 | ```javascript
19 | `helloworld - This is a string`
20 | ```
21 |
22 |
23 |
24 | Template literals are a feature of ES2015 (also known as ES6). In earlier environments, such as on IE11, this code will throw a SyntaxError.
25 |
26 | Like with all modern syntax, in order to write concise, readable code in the latest and greatest version of the language, while still permitting obsolete browsers to understand your code, use a transpiler like [Babel](https://babeljs.io/) to automatically translate your code down to ES5-compatible syntax.
27 |
--------------------------------------------------------------------------------
/content/questions/array-method-binding/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Array Method Binding
3 | tags:
4 | - array
5 | - map
6 | - bind
7 | order: 11
8 | date: '2019-09-29'
9 | answers:
10 | - '1 2 3 // correct'
11 | - 'a b c'
12 | - 'An error is thrown'
13 | - 'Something else'
14 | ---
15 |
16 | What gets logged in the following scenario?
17 |
18 | ```javascript
19 | const map = ['a', 'b', 'c'].map.bind([1, 2, 3]);
20 | map(el => console.log(el));
21 | ```
22 |
23 |
24 |
25 | `['a', 'b', 'c'].map`, when called, will call `Array.prototype.map` with a `this` value of `['a', 'b', 'c']`. But, when used as a *reference*, rather than called, `['a', 'b', 'c'].map` is simply a reference to `Array.prototype.map`.
26 |
27 | `Function.prototype.bind` will bind the `this` of the function to the first parameter (in this case, that's `[1, 2, 3]`), and invoking `Array.prototype.map` with such a `this` results in those items being iterated over and logged.
28 |
--------------------------------------------------------------------------------
/content/questions/a-set-of-objects/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: A Set of Objects
3 | tags:
4 | - set
5 | - object
6 | - spread
7 | order: 2
8 | date: '2019-09-27'
9 | answers:
10 | - '[{a: 1}, {a: 1}] // correct'
11 | - '[{a: 1}]'
12 | ---
13 |
14 | Consider the following `Set` of objects spread into a new array. What gets logged?
15 |
16 | ```javascript
17 | const mySet = new Set([{ a: 1 }, { a: 1 }]);
18 | const result = [...mySet];
19 | console.log(result);
20 | ```
21 |
22 |
23 |
24 | While it's true a `Set` object will remove duplicates, the two values we create our `Set` with are references to different objects in memory, despite having identical key-value pairs. This is the same reason `{ a: 1 } === { a: 1 }` is `false`.
25 |
26 | It should be noted if the set was created using an object variable, say `obj = { a: 1 }`, `new Set([ obj, obj ])` would have only one element, since both elements in the array reference the same object in memory.
27 |
--------------------------------------------------------------------------------
/content/questions/basic-recursion/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Basic Recursion
3 | tags:
4 | - recursion
5 | - slice
6 | order: 17
7 | date: '2019-09-29'
8 | answers:
9 | - 'Hello World'
10 | - 'ello World'
11 | - 'H'
12 | - 'd // correct'
13 | ---
14 |
15 | Consider the following recursive function. If we pass the string `"Hello World"` to it, what gets logged?
16 |
17 | ```javascript
18 | const myFunc = str => {
19 | if (str.length > 1) {
20 | return myFunc(str.slice(1));
21 | }
22 |
23 | return str;
24 | };
25 |
26 | console.log(myFunc('Hello world'));
27 | ```
28 |
29 |
30 |
31 | The first time we call the function, `str.length` is greater than 1 ("Hello World" is 11 characters), so we return the same function called on `str.slice(1)`, which is the string "ello World". We repeat this process until the string is only one character long: the character "d", which gets returned to the initial call of `myFunc`. We then log that character.
32 |
--------------------------------------------------------------------------------
/content/questions/array-pop/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Manipulate an Array with pop()
3 | tags:
4 | - array
5 | - array.pop
6 | order: 53
7 | date: '2019-10-20'
8 | answers:
9 | - 'var removedFromMyArray.pop()'
10 | - 'var removedFromMyArray = myArray.pop() // correct'
11 | - 'myArray.pop(removedFromMyArray)'
12 | - 'var removedFromMyArray.pop()'
13 | ---
14 |
15 | Which of the following options uses the `pop` array method to remove the last item from `myArray`, assigning the "popped off" value to `removedFromMyArray`?
16 |
17 | ```javascript
18 | var myArray = [["John", 23], ["cat", 2]];
19 |
20 | var removedFromMyArray;
21 | ```
22 |
23 |
24 | `.pop()` is used to "pop" a value off of the end of an array. We can store this "popped off" value by assigning it to a variable. In other words, `.pop()` removes the last element from an array and returns that element.
25 |
26 | Any type of entry can be "popped" off of an array - numbers, strings, even nested arrays.
27 |
--------------------------------------------------------------------------------
/content/questions/promise-all-resolve-order/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Promise.all Resolve Order
3 | tags:
4 | - Promise
5 | - Promise.all
6 | order: 7
7 | date: '2019-09-27'
8 | answers:
9 | - '["first", "second"] // correct'
10 | - 'It is random'
11 | ---
12 |
13 | In this question, we have a `timer` function that returns a `Promise` that resolves after a random amount of time. We use `Promise.all` to resolve an array of `timers`. What gets logged?
14 |
15 | ```javascript
16 | const timer = a => {
17 | return new Promise(res =>
18 | setTimeout(() => {
19 | res(a);
20 | }, Math.random() * 100)
21 | );
22 | };
23 |
24 | const all = Promise.all([
25 | timer('first'),
26 | timer('second')
27 | ]).then(data => console.log(data));
28 | ```
29 |
30 |
31 |
32 | The order in which the Promises resolve does not matter to `Promise.all`. We can reliably count on them to be returned in the same order in which they were provided in the array argument.
33 |
--------------------------------------------------------------------------------
/content/questions/batman-v-superman/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Batman v. Superman
3 | tags:
4 | - hof
5 | - function
6 | order: 15
7 | date: '2019-09-29'
8 | answers:
9 | - '"Batman"'
10 | - '"Superman"'
11 | - '"Batman" "Superman" // correct'
12 | - 'Nothing gets logged'
13 | ---
14 |
15 | Consider the following `superheroMaker` function. What gets logged when we pass the following two inputs?
16 |
17 | ```javascript
18 | const superheroMaker = a => {
19 | return a instanceof Function ? a() : a;
20 | };
21 |
22 | console.log(superheroMaker(() => 'Batman'));
23 | console.log(superheroMaker('Superman'));
24 | ```
25 |
26 |
27 |
28 | When passing `() => 'Batman'` to `superheroMaker`, `a` is an instance of `Function`. Therefore, the function gets called, returning the string `Batman`. When passing `'Superman'` to `superheroMaker`, `a` is not an instance of `Function` and therefore the string `'Superman'` is just returned. Therefore, the output is both `Batman` and `Superman`.
29 |
--------------------------------------------------------------------------------
/content/questions/function-equality/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Function Equality
3 | tags:
4 | - function
5 | - equality
6 | order: 18
7 | date: '2019-09-29'
8 | answers:
9 | - 'true true'
10 | - 'true false'
11 | - 'false true // correct'
12 | - 'false false'
13 | ---
14 |
15 | What gets logged when we test the following equality scenarios?
16 |
17 | ```javascript
18 | const a = c => c;
19 | const b = c => c;
20 |
21 | console.log(a == b);
22 | console.log(a(7) === b(7));
23 | ```
24 |
25 |
26 |
27 | In the first test, `a` and `b` are different objects in memory; it doesn't matter that the parameters and return values in each function definition are identical. Therefore, `a` is not equal to `b`. In the second test, `a(7)` returns the number `7` and `b(7)` returns the number `7`. These primitive types are strictly equal to each other.
28 |
29 | In this case, the equality (`==`) vs identity (`===`) comparison operators don't matter; no type coercion will affect the result.
30 |
--------------------------------------------------------------------------------
/content/questions/identity-crisis/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Identity Crisis
3 | tags:
4 | - comparison
5 | - object
6 | - equality
7 | order: 58
8 | date: Fri Oct 25 2019 14:27:00 GMT+0300 (Eastern European Summer Time)
9 | answers:
10 | - 'true true true true'
11 | - 'true false true true'
12 | - 'true true false true // correct'
13 | - 'true true false false'
14 | - 'false false false false'
15 | ---
16 |
17 | Consider the following comparison function and its applications. What gets logged?
18 |
19 | ```javascript
20 | const compare = a => a === a;
21 |
22 | console.log(compare(null));
23 | console.log(compare(undefined));
24 | console.log(compare(NaN));
25 | console.log(compare([NaN]));
26 | ```
27 |
28 |
29 |
30 | Out of all JavaScript values, `NaN` aka Not-A-Number is the only one that compares unequal to every other value, including itself.
31 |
32 | Note that `[NaN]` is just a regular array that contains a single element so it will be always equal to itself.
33 |
--------------------------------------------------------------------------------
/src/utils/shouldRenderContributor.js:
--------------------------------------------------------------------------------
1 | const gatsbyPeeps = new Set([
2 | 71047,
3 | 25650701,
4 | 735227,
5 | 35560568,
6 | 419821,
7 | 15214,
8 | 4155121,
9 | 6865958,
10 | 693728,
11 | 3924690,
12 | 7007253,
13 | 381801,
14 | 28694502,
15 | 265415,
16 | 17114329,
17 | 6064830,
18 | 7683393,
19 | 760686,
20 | 561983,
21 | 1862172,
22 | 4315,
23 | 162735,
24 | 14151855,
25 | 22216761,
26 | 2519959,
27 | 5244986,
28 | 5198,
29 | 81942,
30 | 925443,
31 | 589596,
32 | 98955,
33 | 15073503,
34 | 74385,
35 | 28495352,
36 | 176013,
37 | 11172548,
38 | 5188868,
39 | 607807,
40 | 2753425
41 | ]);
42 |
43 | export const shouldRenderContributor = id =>
44 | !gatsbyPeeps.has(id);
45 |
46 | export const shuffle = arr => {
47 | const array = [...arr];
48 | for (let i = array.length - 1; i > 0; i--) {
49 | let j = Math.floor(Math.random() * (i + 1));
50 | [array[i], array[j]] = [array[j], array[i]];
51 | }
52 | return array;
53 | };
54 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/content/questions/floating-point-precision/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Floating-Point Precision
3 | tags:
4 | - floating-point
5 | - decimal
6 | - rounding
7 | order: 39
8 | date: '2019-10-07'
9 | answers:
10 | - 'true'
11 | - 'false // correct'
12 | ---
13 |
14 | Consider the following scenario. What gets logged?
15 |
16 | ```javascript
17 | const a = 0.1;
18 | const b = 0.2;
19 | const c = 0.3;
20 |
21 | console.log(a + b === c);
22 | ```
23 |
24 |
25 |
26 | In computing, decimal numbers as we know them are most commonly represented using floating-point arithmetic. Floating-point numbers only approximate real numbers and cannot accurately represent numbers like `0.1`, `0.2` or `0.3` at all. In the case of `0.1 + 0.2`, this results in small rounding errors before we even get to the addition part. The final sum then equals to `0.30000000000000004`.
27 |
28 | Similarly, the decimal system cannot represent `1/3` (one third) accurately. And if we took a rounded value like `0.333`, you wouldn't expect `0.333 + 0.333 + 0.333` to add up to `1`, either.
--------------------------------------------------------------------------------
/content/questions/array-method-callbacks/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Array Method Callbacks
3 | tags:
4 | - array
5 | - callbacks
6 | order: 58
7 | date: Sun Oct 20 2019 15:26:39 GMT-0700 (Pacific Daylight Time)
8 | answers:
9 | - '5'
10 | - '4'
11 | - '1'
12 | - '0 // correct'
13 | ---
14 |
15 | What gets logged in the following code?
16 |
17 | ```javascript
18 | let i = 0;
19 |
20 | const arr = new Array(5);
21 | arr.forEach(() => i++);
22 |
23 | console.log(i);
24 | ```
25 |
26 |
27 |
28 | Array methods like `map`, `filter`, `reduce`, `forEach`, etc take a callback as the first parameter, which is executed for every element in the array. The Array constructor, when given an integer between 0 and (232 - 1), will return a sparse array, which has a length property equal to the given integer. The returned array is "sparse" because its slots are empty; it does not have any own-properties, other than `.length`. (In contrast, the array `[undefined]` *does* have an own-property of `0`, even though the value at that property is `undefined`.)
29 |
--------------------------------------------------------------------------------
/content/questions/prototypal-inheritance/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Prototypal Inheritance
3 | tags:
4 | - prototype
5 | order: 4
6 | date: '2019-09-27'
7 | answers:
8 | - 'woof // correct'
9 | - 'arf'
10 | ---
11 |
12 | In this question, we have a `Dog` constructor function. Our dog obviously knows the speak command. What gets logged in the following example when we ask Pogo to speak?
13 |
14 | ```javascript
15 | function Dog(name) {
16 | this.name = name;
17 | this.speak = function() {
18 | return 'woof';
19 | };
20 | }
21 |
22 | const dog = new Dog('Pogo');
23 |
24 | Dog.prototype.speak = function() {
25 | return 'arf';
26 | };
27 |
28 | console.log(dog.speak());
29 | ```
30 |
31 |
32 |
33 | Every time we create a new `Dog` instance, we set the `speak` property of that instance to be a function returning the string `woof`. Since this is being set every time we create a new `Dog` instance, the interpreter never has to look farther up the prototype chain to find a `speak` property. As a result, the `speak` method on `Dog.prototype.speak` never gets used.
34 |
--------------------------------------------------------------------------------
/content/questions/string-interpolation/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: String Interpolation
3 | tags:
4 | - strings
5 | - interpolation
6 | - template literals
7 | order: 54
8 | date: Fri Oct 18 2019 22:06:13 GMT+0530 (India Standard Time)
9 | answers:
10 | - "Soon we must all choose between what is right and what is easy"
11 | - "Soon we must all choose between what is right and what is difficult // correct"
12 | - "Soon we must all choose between what is wrong and what is easy"
13 | - "Soon we must all choose between what is wrong and what is difficult"
14 | ---
15 |
16 | What's the value of `output`?
17 |
18 | ```javascript
19 | const output = `Soon we must all choose between what is ${[] ? 'right' : 'wrong'} and what is ${(() => false) ? 'difficult' : 'easy'}`;
20 | ```
21 |
22 |
23 |
24 | As `[]` is a truthy value, the first conditional evaluates to `'right'`.
25 |
26 | With the second conditional operator, we created a function `() => false`, but never called it. Functions, like all objects, are truthy values is JavaScript, hence `'difficult'` is the result.
27 |
--------------------------------------------------------------------------------
/content/questions/type-coercion/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Implicit Type Coercion
3 | tags:
4 | - coercion
5 | - types
6 | - type casting
7 | order: 52
8 | date: '2019-10-19'
9 | answers:
10 | - 'greeting + year.toString()'
11 | - 'greeting + String(year)'
12 | - 'greeting + year // correct'
13 | ---
14 |
15 | Consider the following variables `greeting` and `year`.
16 |
17 | ```javascript
18 | const greeting = "Hello";
19 | const year = 2019;
20 | ```
21 |
22 | Which of the following is an example of implicit coercion in JavaScript?
23 |
24 |
25 |
26 | Some programming languages have a concept called type casting. This means that, if you want to convert one type to another type, you have to make the conversion explicit. In JavaScript there is a mechanism called _implicit coercion_, which converts types to other types as necessary. In this case, the addition operator `+` automatically converts `2019` to a string so it can be concatenated with the string `"Hello"`. In contrast, `year.toString()` and `String(year)` are both *explicitly* converting it to a string.
27 |
--------------------------------------------------------------------------------
/src/components/learn-more.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export const LearnMore = () => (
4 |
33 |
34 | >
35 | );
36 | };
37 |
38 | export default Bio;
39 |
--------------------------------------------------------------------------------
/content/questions/arrow-functions/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Arrow Functions
3 | tags:
4 | - arrow functions
5 | - functions
6 | - binding
7 | order: 39
8 | date: Mon Oct 07 2019 16:26:43 GMT+0530 (India Standard Time)
9 | answers:
10 | - 'Border Collie, Wooh'
11 | - 'Border Collie, undefined'
12 | - 'undefined, Wooh // correct'
13 | - 'undefined, undefined'
14 | ---
15 |
16 | What gets logged in the following code?
17 |
18 | ```javascript
19 | let dog = {
20 | breed: "Border Collie",
21 | sound: "Wooh",
22 | getBreed: () => {
23 | return this.breed;
24 | },
25 | getSound: function() {
26 | return this.sound;
27 | }
28 | };
29 | console.log(dog.getBreed(), dog.getSound());
30 | ```
31 |
32 |
33 |
34 | The `this` inside an arrow function does not depend on how the function was called. Instead, they inherit the `this` of the parent scope. This is called "lexical scoping". In sloppy mode, `this` on the top level refers to the global object, so `getBreed`'s `this.breed` refers to the `breed` property on the global object, which doesn't exist.
35 |
36 |
--------------------------------------------------------------------------------
/content/questions/delete-object-properties/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Deleting Properties from an Object
3 | tags:
4 | - object
5 | order: 33
6 | date: '2019-10-05'
7 | answers:
8 | - 'A'
9 | - 'B // correct'
10 | - 'C'
11 | - 'D'
12 | ---
13 |
14 | Which of the following is a valid way to delete the property `color` from the `car` object?
15 |
16 | ```javascript
17 | const car = {
18 | make: 'Mercedez Benz',
19 | year: '2019',
20 | color: 'black'
21 | };
22 |
23 | // A
24 | car.delete('color');
25 |
26 | // B
27 | delete car.color;
28 |
29 | // C
30 | delete car[color];
31 |
32 | // D
33 | car.color.delete();
34 | ```
35 |
36 |
37 |
38 | You can use the JavaScript [delete operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete) to remove a property from an object.
39 |
40 | Both option A and D will give a TypeError, because neither `car.delete` nor `car.color.delete` is a function.
41 |
42 | Option C will give a ReferenceError becuase `color` is not defined. However, `delete car['color']` will work - notice the quotation marks around `color`.
43 |
--------------------------------------------------------------------------------
/content/questions/confusing-date/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Date Constructor
3 | tags:
4 | - date
5 | - constructor
6 | order: 49
7 | date: '2019-10-11'
8 | answers:
9 | - '1/1/2019 2/1/2019 // correct'
10 | - '1/1/2019 1/1/2019'
11 | ---
12 |
13 | Consider the following code block which calls the Date constructor with 2 type of values. In a US environment, what will be the output of `console.log`?
14 |
15 | ```javascript
16 | let a = new Date("2019,1,1").toLocaleDateString();
17 | let b = new Date(2019,1,1).toLocaleDateString();
18 | console.log(a, b);
19 | ```
20 |
21 |
22 |
23 | The Date constructor, `new Date()`, creates a date object at a given date or the current date if no date is given. It can be called in many ways. If the Date constructor is passed as a string, JavaScript will attempt to interpret the string as a date. in this case, "2019,1,1" is interpreted as January 1, 2019. If the Date constructor is passed three numbers, the first value will be interpreted as the year, the second value the month, and the third the day. The catch here is JavaScript starts its month indexing at 0, so month `1` is February!
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Gatsbyjs
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/content/questions/array-as-boolean/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Array as boolean
3 | tags:
4 | - array
5 | - implicit convesion
6 | - boolean
7 | - if statement
8 | order: 59
9 | date: Thu Oct 24 2019 16:38:30 GMT+0200 (Central European Summer Time)
10 | answers:
11 | - '[true, true] // correct'
12 | - '[false, true]'
13 | - '[true, false]'
14 | - '[false, false]'
15 | ---
16 |
17 | What does the below function return?
18 |
19 | ```javascript
20 | function ArrayBoolean(){
21 | if([] && [1])
22 | return [true, true];
23 | else if([] && ![1])
24 | return [true,false];
25 | else if(![] && [1])
26 | return [false,true];
27 | else
28 | return [false,false];
29 | }
30 | ArrayBoolean();
31 | ```
32 |
33 |
34 | In JavaScript, both empty and non empty arrays are truthy, like all objects. This is not the same thing as comparison - for example, if the arrays were loosely compared to a Boolean, the results would be different. `[] == false` would evaluate to `true` because the empty array, when converted into a primitive, is falsey.
35 |
36 | The first `if` statement is fulfilled, so `[true, true]` is returned.
37 |
--------------------------------------------------------------------------------
/content/questions/object-clone-stringify-mutation/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Object Cloning (JSON.parse + JSON.stringify)
3 | tags:
4 | - object
5 | - cloning
6 | - mutation
7 | order: 27
8 | date: '2019-10-05'
9 | answers:
10 | - 'Joe Nested // correct'
11 | - 'Bob Changed'
12 | - 'Joe Changed'
13 | - 'Bob Nested'
14 | ---
15 |
16 | Consider objects `a` and `b` below. What gets logged?
17 |
18 | ```javascript
19 | const a = {
20 | stringField: 'Joe',
21 | nestedField: {field: 'Nested'}
22 | };
23 | const b = JSON.parse(JSON.stringify(a));
24 | b.stringField = 'Bob';
25 | b.nestedField.field = 'Changed';
26 | console.log(
27 | a.stringField,
28 | a.nestedField.field
29 | );
30 | ```
31 |
32 |
33 |
34 | `b = JSON.parse(JSON.stringify(a))` will perform a deep copy of object `a` and assign it to `b`. `b` will not contain any references to `a` and thus mutating any fields in `b` will not affect any fields in `a`. This will, however, only properly copy valid JSON values. See [MDN Description](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#Description) for a more detailed explanation.
35 |
--------------------------------------------------------------------------------
/content/questions/array-object-efficiency/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Array-to-Object Efficiency
3 | tags:
4 | - array
5 | - object
6 | - spread
7 | - reduce
8 | order: 14
9 | date: '2019-09-29'
10 | answers:
11 | - 'a'
12 | - 'b // correct'
13 | ---
14 |
15 | Both `a` and `b` are objects with the same properties and values. Which is created more efficiently?
16 |
17 | ```javascript
18 | const arr = [1, 2, 3];
19 |
20 | const a = arr.reduce(
21 | (acc, el, i) => ({ ...acc, [el]: i }),
22 | {}
23 | );
24 |
25 | const b = {};
26 | for (let i = 0; i < arr.length; i++) {
27 | b[arr[i]] = i;
28 | }
29 | ```
30 |
31 |
32 |
33 | When `b` is being set, the `b[arr[i]]` property is set to the current index on each iteration. When `a` is being set, the spread syntax (`...`) will create a shallow copy of the accumulator object (`acc`) on each iteration and additionally set the new property. This shallow copy is more expensive than not performing a shallow copy; `a` requires the construction of 2 intermediate objects before the result is achieved, whereas `b` does not construct any intermediate objects. Therefore, `b` is being set more efficiently.
34 |
--------------------------------------------------------------------------------
/content/questions/deep-object-mutability/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Deep Object Mutability
3 | tags:
4 | - object
5 | - mutability
6 | - freeze
7 | order: 3
8 | date: '2019-09-27'
9 | answers:
10 | - 'Daffodil // correct'
11 | - 'Buttercup'
12 | - 'An error is thrown'
13 | ---
14 |
15 | Consider the following object representing a user, Joe, and his dog, Buttercup. We use `Object.freeze` to preserve our object and then attempt to mutate Buttercup's name. What gets logged?
16 |
17 | ```javascript
18 | const user = {
19 | name: 'Joe',
20 | age: 25,
21 | pet: {
22 | type: 'dog',
23 | name: 'Buttercup'
24 | }
25 | };
26 |
27 | Object.freeze(user);
28 |
29 | user.pet.name = 'Daffodil';
30 |
31 | console.log(user.pet.name);
32 | ```
33 |
34 |
35 |
36 | `Object.freeze` will perform a shallow freeze on an object, but will not protect deep properties from being mutated. In this example, we would not be able to mutate `user.age`, but we have no problem mutating `user.pet.name`. If we feel we need to protect an object from being mutated "all the way down," we could recursively apply `Object.freeze` or use an existing "deep freeze" library.
37 |
--------------------------------------------------------------------------------
/content/questions/event-scheduling/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Event Scheduling
3 | tags:
4 | - events
5 | - setTimeout
6 | - setInterval
7 | order: 26
8 | date: '2019-10-03'
9 | answers:
10 | - '1, 2, 3, 4'
11 | - '4, 2, 1, 3'
12 | - '1, 4, 3, 2 // correct'
13 | - '4, 3, 2, 1'
14 | ---
15 |
16 | In what order will the numbers 1-4 be logged to the console when the code below is executed?
17 |
18 | ```javascript
19 | (function() {
20 | console.log(1);
21 | setTimeout(function() {
22 | console.log(2);
23 | }, 1000);
24 | setTimeout(function() {
25 | console.log(3);
26 | }, 0);
27 | console.log(4);
28 | })();
29 | ```
30 |
31 |
32 |
33 | `1` and `4` are displayed first since they are logged by simple calls to `console.log()` without any delay.
34 | `2` is displayed after `3` because `2` is being logged after a delay of 1000 msecs (i.e., 1 second) whereas `3` is being logged after a delay of 0 msecs. Note that, despite `3` having a delay of 0 msecs, its code will only be executed after the current call stack is cleared. If this concept is new to you, consider checking out the [JS concurrency model/event loop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop).
35 |
--------------------------------------------------------------------------------
/content/questions/callback-set-timeout/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Callback setTimeOut
3 | tags:
4 | - callback function
5 | - time intervals
6 | order: 55
7 | date: Sun Oct 20 2019 12:08:06 GMT-0700 (Pacific Daylight Time)
8 | answers:
9 | - 'A'
10 | - 'B // correct'
11 | - 'C'
12 | - 'D'
13 | - 'None of the above'
14 | ---
15 |
16 | Which of the following functions will add two variables and pass the sum to a callback function after 2 seconds?
17 |
18 | ```javascript
19 | // A
20 | const add = (x, y, callback) => {
21 | setTimeout(() => {
22 | callback(x + y);
23 | }, 2);
24 | };
25 |
26 | // B
27 | const add = (x, y, callback) => {
28 | setTimeout(() => {
29 | callback(x + y);
30 | }, 2000);
31 | };
32 |
33 | // C
34 | const add = (x, y, callback) => {
35 | setTimeout(() => {
36 | callback(x + y, 2);
37 | });
38 | };
39 |
40 | // D
41 | const add = (x, y, callback) => {
42 | setTimeout(() => {
43 | callback(x + y, 2000);
44 | });
45 | };
46 | ```
47 |
48 |
49 | The `setTimeout` function generally takes two variables: the first variable is the function to be executed, and the second variable is the interval, in milliseconds, after which the function gets executed.
50 |
--------------------------------------------------------------------------------
/content/questions/off-to-the-races/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Off to the Races
3 | tags:
4 | - promise
5 | - race-condition
6 | - iterable
7 | order: 40
8 | date: '2019-10-06'
9 | answers:
10 | - 'Hello'
11 | - 'Goodbye'
12 | - 'Oops!'
13 | - 'Something went wrong... // correct'
14 | - 'TypeError: Promise.race is not a function'
15 | ---
16 |
17 | What gets logged?
18 |
19 | ```javascript
20 | const p1 = new Promise((resolve, reject) =>
21 | setTimeout(resolve, 100, 'Hello'));
22 |
23 | const p2 = new Promise((resolve, reject) =>
24 | setTimeout(resolve, 120, 'Goodbye'));
25 |
26 | const p3 = new Promise((resolve, reject) =>
27 | setTimeout(reject, 10, 'Oops!'));
28 |
29 | Promise.race([p1, p2, p3])
30 | .then((result) => console.log(result))
31 | .catch((reason) => console.log("Something went wrong..."));
32 | ```
33 |
34 |
35 |
36 | Given an iterable of Promises, [`Promise.race()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race) returns a Promise that resolves or rejects with the value of the first
37 | Promise that settles (the first Promise that resolves or rejects).
38 |
39 | In this case, `p3` settles first, rejecting after 10 ms and falling into the `catch()` handler.
40 |
--------------------------------------------------------------------------------
/content/questions/array-compare-2/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Array Compare - 2
3 | tags:
4 | - array
5 | - comparison
6 | - type coercion
7 | order: 58
8 | date: Wed Oct 23 2019 23:39:34 GMT-0700 (Pacific Daylight Time)
9 | answers:
10 | - 'true true true'
11 | - 'false false false'
12 | - 'true true false // correct'
13 | - 'false false true'
14 | ---
15 |
16 | Consider the following block of code. What gets logged?
17 |
18 | ```javascript
19 | var a = [9];
20 | var b = [10];
21 |
22 | console.log(a == 9);
23 | console.log(b == 10);
24 | console.log(a < b);
25 | ```
26 |
27 |
28 |
29 | When using `==` to compare an array with a number, JavaScript tries to coerce the array to a number, which is possible when the array contains a single numeric value. Here, `[9]` turns into `9`, and `[10]` turns into `10`, and `9 == 9` and `10 == 10` are both `true`.
30 |
31 | When comparing arrays with `<` or `>`, the arrays are instead coerced to strings (`[9] < [10]` turns into `'9' < '10'`). When comparing strings, JavaScript uses lexicographical order, which means the strings are compared to each other one character at a time. The first characters that are different are the ones at the `[0]`th index, so the comparison done is `"9" < "1"`, which is false.
32 |
--------------------------------------------------------------------------------
/content/questions/array-compare/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Array Compare
3 | tags:
4 | - array
5 | - reference
6 | - comparison
7 | order: 36
8 | date: '2019-10-06'
9 | answers:
10 | - 'true, true, false // correct'
11 | - 'true, true, true'
12 | - 'true, false, false'
13 | - 'false, false false'
14 | ---
15 |
16 | Consider the following variables. What gets logged?
17 |
18 | ```javascript
19 | var a = [1, 2, 3];
20 | var b = [1, 2, 3];
21 | var c = '1,2,3';
22 |
23 | console.log(a == c);
24 | console.log(b == c);
25 | console.log(a == b);
26 | ```
27 |
28 |
29 |
30 | When comparing either `a` or `b` to `c` using the equality operator (`==`), the JavaScript interpreter will attempt to use the array's built-in `toString` method to first convert the array to a string. For both `a` and `b`, the `a.toString()` method returns `'1,2,3'`. This is strictly equal to `c`, so both `a == c` and `b == c` are `true`!
31 |
32 | Non-primitive values - that is, objects (including functions and arrays) are held by reference. When comparing two objects both the equality (`==`) and identity (`===`) operators will simply check whether the references match (the underlying values are not considered). In this case, `a` and `b` are references to different objects in memory, so `a == b` is `false`.
33 |
--------------------------------------------------------------------------------
/content/questions/array-method-slice/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Array Method
3 | tags:
4 | - Array methods
5 | - slice
6 | order: 55
7 | date: Sun Oct 20 2019 13:01:02 GMT-0700 (Pacific Daylight Time)
8 | answers:
9 | - '["Banana", "Lemon"]'
10 | - '["Lemon", "Apple"]'
11 | - '["Orange", "Lemon"] // correct'
12 | ---
13 |
14 | What will the value of `citrus` be in the below code?
15 |
16 | ```javascript
17 | var fruits = ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango'];
18 | var citrus = fruits.slice(1, 3);
19 | ```
20 |
21 |
22 | The reason why the result will be `["Orange", "Lemon"]` is that the two parameters `.slice` accepts are:
23 |
24 | * The start index, inclusive
25 | * The end index, *exclusive* (the item at the end index will not be included in the result)
26 |
27 | `.slice` does not alter the original array. It returns a shallow copy of elements from the original array. It's only a shallow copy, so if an object is *mutated* in one of the arrays after slicing, the same object in the other array will have changed too, because the objects both point to the same location in memory. In contrast, *reassigning* any value in one array, primitive or otherwise, will have no effect on the other array. Simiarly, adding or removing items from one array will not affect the other.
28 |
--------------------------------------------------------------------------------
/content/questions/inceptionloop/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Direction of Loops
3 | tags:
4 | - Loops
5 | order: 57
6 | date: Sun Oct 20 2019
7 | answers:
8 | - 'Scans across a row before going to the one below // correct'
9 | - 'Scans down the column before going to the next to the right'
10 | - 'None of the above'
11 | ---
12 |
13 | In which direction will the following code scan an image?
14 |
15 | ```javascript
16 | const image = new Image();
17 | const maxHeight = image.height + 1;
18 | const maxWidth = image.width + 1;
19 |
20 | for (let i = 0; i < maxHeight; i++) {
21 | for (let j = 0; j < maxWidth; j++) {
22 | // Obtaining values of pixels, assuming function getPixel(y, x) takes argument y as Y-coordinate and x as X-coordinate
23 | const pixel = getPixel(i, j);
24 | const pixelValues = {
25 | red: pixel.getRed(),
26 | green: pixel.getGreen(),
27 | blue: pixel.getBlue()
28 | };
29 | // Update pixel color scheme
30 | pixelValues.red /= 2;
31 | pixelValues.green /= 3;
32 | pixelValues.blue *= 2;
33 | }
34 | }
35 | ```
36 |
37 |
38 |
39 | Option A is the correct answer becuase value `i` will only update once all of the values of `j` have been processed. So, it will read across the row first before going to the next one below. Note all the pixel code is essentially a distraction.
40 |
--------------------------------------------------------------------------------
/content/questions/array-sort-comparison/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Array Sort Comparison
3 | tags:
4 | - arrays
5 | - sort
6 | - comparison
7 | order: 1
8 | date: '2019-09-27'
9 | answers:
10 | - true true true
11 | - true true false // correct
12 | - false false false
13 | - true false true
14 | ---
15 |
16 | Consider the following arrays. What gets logged in various sorting conditions?
17 |
18 | ```javascript
19 | const arr1 = ['a', 'b', 'c'];
20 | const arr2 = ['b', 'c', 'a'];
21 |
22 | console.log(
23 | arr1.sort() === arr1,
24 | arr2.sort() == arr2,
25 | arr1.sort() === arr2.sort()
26 | );
27 | ```
28 |
29 |
30 |
31 | There are a couple concepts at play here. First, the array `sort` method sorts your original array and also returns a reference to that array. This means that when you write `arr2.sort()`, the `arr2` array object is sorted.
32 |
33 | It turns out, however, the sort order of the array doesn't matter when you're comparing objects. Since `arr1.sort()` and `arr1` point to the same object in memory, the first equality test returns `true`. This holds true for the second comparison as well: `arr2.sort()` and `arr2` point to the same object in memory.
34 |
35 | In the third test, the sort order of `arr1.sort()` and `arr2.sort()` are the same; however, they still point to different objects in memory. Therefore, the third test evaluates to `false`.
36 |
--------------------------------------------------------------------------------
/content/questions/pass-by-value/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Pass by Value
3 | tags:
4 | - object
5 | - mutability
6 | - data types
7 | order: 24
8 | date: '2019-10-02'
9 | answers:
10 | - 'football, "Lisa prefers Johnny", Chris R'
11 | - 'roofsitting, "Lisa prefers Mark", Doggy'
12 | - 'roofsitting, "Lisa prefers Johnny", Doggy // correct'
13 | - 'football, "Lisa prefers Mark", Chris R'
14 | ---
15 |
16 | When setting variables equal to each other and then changing one of them, does it change the other? Consider the following code. What is logged?
17 |
18 | ```javascript
19 | let a1 = {
20 | name: 'Johnny',
21 | hobby: 'football'
22 | };
23 |
24 | let b1 = 'Lisa prefers Johnny';
25 |
26 | let c1 = ['Denny', 'Michelle', 'Chris R'];
27 |
28 | let a2 = a1;
29 | let b2 = b1;
30 | let c2 = c1;
31 |
32 | a2.hobby = 'roofsitting';
33 | b2 = 'Lisa prefers Mark';
34 | c2[2] = 'Doggy';
35 |
36 | console.log(a1.hobby);
37 | console.log(b1);
38 | console.log(c1[2]);
39 | ```
40 |
41 |
42 |
43 | Because `a2` and `c2` refer to the same objects in memory as `a1` and `c1`, when their properties `hobby` and `[2]` were changed, those changes could also be seen through `a1` and `c1`. The change made to `b2` was not changing a property, rather, replacing the `b2` variable itself. Replacing a variable with a new value has no effect on the original value, so `b1` remained unchanged.
44 |
45 |
--------------------------------------------------------------------------------
/content/questions/digit-with-dots-in-js/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Two Many Dots?
3 | tags:
4 | - numbers
5 | - properties
6 | order: 44
7 | date: '2019-10-08'
8 | answers:
9 | - '[1, 2, 3, 4, 5]'
10 | - 'undefined // correct'
11 | - 'Syntax error'
12 | ---
13 |
14 | What is the return of the following `console.log`?
15 |
16 | ```javascript
17 | const n = 5;
18 |
19 | console.log(1..n); // ?
20 | ```
21 |
22 |
23 |
24 | This is not a syntax error. Rather, to call a method directly on a `Number.prototype`, two dots are required for it to not be interpreted as a decimal. In this case, `1..n` tries to access the property `n` on `1`, which is `undefined`. A practical example of this would be `1..toString()`, which would result in the string `"1"`.
25 |
26 | What's going on here is that a decimal point is permitted at the end of a number even if there are no decimal digits. `1.` is interpreted as a numeric literal equivalent to `1` - the dot is an optional decimal point, and is *not* indicating property access. If you add *another* `.`, the interpreter is forced to treat the second `.` as the property access operator.
27 |
28 | Another way to call a method on a numeric literal without the confusing `..` is to surround the number in parentheses, eg `(1).toString()`.
29 |
30 | To see more info on this notation, refer to: [Two dots to call a method](https://javascript.info/number#tostring-base).
31 |
--------------------------------------------------------------------------------
/content/questions/operator-associativity/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Operator Associativity
3 | tags:
4 | - operator
5 | - associativity
6 | - precedence
7 | order: 46
8 | date: '2019-10-09'
9 | answers:
10 | - true and true
11 | - true and false // correct
12 | - false and false
13 | - undefined and undefined
14 | - SyntaxError
15 | ---
16 |
17 | Given the following lines, what will be the output?
18 |
19 | ```javascript
20 | console.log(1 < 2 < 3);
21 | console.log(3 > 2 > 1);
22 | ```
23 |
24 |
25 |
26 | The operators `<` and `>` follow left-to-right associativity, meaning that they will be interpreted starting from the left. For demonstration, left-to-right evaluated expressions like `a OP b OP c` can be written as `(a OP b) OP c`.
27 |
28 | Following this scheme, the first expression becomes `(1 < 2) < 3`. The part in parenthesis evaluates to `true` leaving `true < 3`. Because the right-hand side is a number, the `true` on the left-hand side is coerced into the number `1`. Hence, the whole expression evaluates to `true`.
29 |
30 | In the second example (visualized as `(3 > 2) > 1`), the first part `(3 > 2)` evaluates to `true`. The remaining portion `true > 1` then gets converted to `1 > 1`. As `1` is not greater than itself, the whole expression evaluates to `false`.
31 |
--------------------------------------------------------------------------------
/content/questions/triple-plus/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Triple Plus
3 | tags:
4 | - type coercion
5 | - operation precedence
6 | order: 58
7 | date: Wed Oct 23 2019 21:29:27 GMT-0700 (Pacific Daylight Time)
8 | answers:
9 | - '44 4'
10 | - '8 5'
11 | - '7 5 // correct'
12 | - '43 5'
13 | - 'Syntax Error'
14 | ---
15 |
16 | Consider the following code block. What is the result?
17 |
18 | ```javascript
19 | let b = "4";
20 |
21 | console.log(b +++ 3, b);
22 | ```
23 |
24 |
25 |
26 | The Postfix Increment operator (`++`) takes precedence over the addition operator (`+`), and will coerce strings to numbers. The expression with the operator will evaluate to the coerced value, and (in line with the "Post" part of "Postfix") will increment the variable immediately afterwards.
27 |
28 | The code block in the question is equivalent to
29 |
30 | ```javascript
31 | let b = "4";
32 | console.log((b++) + 3, b);
33 | ```
34 |
35 | First, `b` is coerced to a number, and the increment expression evaluates to that number:
36 |
37 | ```javascript
38 | console.log((4) + 3, b);
39 | ```
40 |
41 | `b` is then incremented from `4` to `5`. This resolves to:
42 |
43 | ```javascript
44 | console.log(7, 5);
45 | ```
46 |
47 | See MDN's article on operator precedence.
48 |
--------------------------------------------------------------------------------
/content/questions/async-await/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Async/Await
3 | tags:
4 | - es6
5 | - promise
6 | order: 39
7 | date: Mon Oct 07 2019 09:40:20 GMT-0700 (Mountain Standard Time)
8 | answers:
9 | - 'first!'
10 | - 'done! // correct'
11 | - 'JavaScript error'
12 | - 'Something else'
13 | ---
14 |
15 | Consider the following async function and its output. What will be displayed to the console when calling the `f()` function?
16 |
17 | ```javascript
18 | async function f() {
19 | let result = 'first!';
20 | let promise = new Promise((resolve, reject) => {
21 | setTimeout(() => resolve('done!'), 1000);
22 | });
23 |
24 | result = await promise;
25 |
26 | console.log(result);
27 | }
28 |
29 | f();
30 | ```
31 |
32 |
33 |
34 | The function execution "pauses" at the line `await promise` and resumes when the promise settles, with the resolve value of the promise being assigned to `result`. So, the code above shows "done!" after one second.
35 |
36 | Let’s emphasize: `await` makes the current function pause until the promise settles, and then goes on with the result. This doesn’t cost any CPU resources, because the engine can do other jobs
37 | in the meantime: execute other scripts, handle events etc.
38 |
39 | `await` is mostly just a more elegant way to get the promise result than `promise.then`. `await` is easier to read and write, especially when multiple Promises need to be waited for, which would otherwise require somewhat-unwieldy `.then` chains.
40 |
--------------------------------------------------------------------------------
/content/questions/lexical-scope/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Lexical Scope
3 | tags:
4 | - scope
5 | order: 52
6 | date: '2019-10-20'
7 | answers:
8 | - 2 // correct
9 | - '3'
10 | - 'Undefined'
11 | ---
12 |
13 | Fun Lexical Scope! What do you think will be printed?
14 |
15 | ```javascript
16 | function printSomething() {
17 | console.log( something );
18 | }
19 |
20 | function invokePrintSomething() {
21 | var something = 3;
22 | printSomething();
23 | }
24 |
25 | var something = 2;
26 |
27 | invokePrintSomething();
28 | ```
29 |
30 |
31 |
32 | When a variable is referenced in JavaScript, the interpreter will try to find which binding it references by looking through the ancestor blocks and functions to see if a variable with that name is declared in that block or function. The nearest ancestor block (or the top level) which defines the variable with `const`, `let`, or `var` will be identified as the binding to use.
33 |
34 | Here, when `invokePrintSomething` is called and the `var something = 3` is found, the interpreter will see that the `something` is initialized with `var` in the same block, so the binding is to a variable local to `invokePrintSomething`. Then, when `printSomething` is called, and it comes across `console.log( something );`, it will look to its ancestor blocks to see where a variable named `something` is defined. The nearest (and only) ancestor block is the top level, with a `var something` which currently holds the value of `2`, so `2` gets logged.
35 |
--------------------------------------------------------------------------------
/scripts/new-question/index.js:
--------------------------------------------------------------------------------
1 | const { readdirSync, mkdirSync, readFileSync, writeFileSync } = require('fs');
2 | const template = require('lodash.template');
3 | const path = require('path');
4 |
5 | function getDirectories(path) {
6 | return readdirSync(path, { withFileTypes: true })
7 | .filter(dirent => dirent.isDirectory())
8 | .map(dirent => dirent.name);
9 | }
10 |
11 | function init() {
12 | const agrs = process.argv.slice(2);
13 |
14 | if (!agrs.length) {
15 | throw new Error('Please, specify question title');
16 | }
17 |
18 | const questionName = agrs[0];
19 | const srcDir = `${path.dirname(require.main.filename)}/../../content/questions`;
20 | const existingQuestions = getDirectories(srcDir);
21 |
22 | if (existingQuestions.indexOf(questionName) > -1) {
23 | throw new Error(`Question ${questionName} already exists. Please, specify another name`);
24 | }
25 |
26 | mkdirSync(`${srcDir}/${questionName}`, (err) => {
27 | if (err) throw err;
28 | });
29 |
30 | const fileTemplate = readFileSync(`${path.dirname(require.main.filename)}/index.md`, 'utf8');
31 | const blankQuestionTmpl = template(fileTemplate);
32 |
33 | writeFileSync(`${srcDir}/${questionName}/index.md`, blankQuestionTmpl({
34 | order: existingQuestions.length,
35 | date: new Date(),
36 | }));
37 |
38 | console.info('All done!');
39 | }
40 |
41 | try {
42 | init();
43 | } catch (e) {
44 | console.error(e.message);
45 | process.exit(-1);
46 | }
47 |
48 | process.exit(0);
49 |
--------------------------------------------------------------------------------
/content/questions/copying-arrays/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Copying Arrays
3 | tags:
4 | - fetch
5 | - spread
6 | order: 32
7 | date: '2019-10-05'
8 | answers:
9 | - 'A'
10 | - 'B'
11 | - 'C'
12 | - 'A and B'
13 | - 'B and C // correct'
14 | - 'A, B, and C'
15 | ---
16 |
17 | Which of the following methods are valid ways to copy `mainArray` ?
18 |
19 | ```javascript
20 | const mainArray = ['one', 'two', 'three', 'five', 'four'];
21 |
22 | // A
23 | const a = mainArray;
24 |
25 | // B
26 | const b = [ ...mainArray ];
27 |
28 | // C
29 | const c = [];
30 | mainArray.forEach(item => {
31 | c.push(item);
32 | });
33 | ```
34 |
35 |
36 |
37 | Option A just creates a new reference to the same array. In order to copy all the values from an array, you'll need to iterate through the array and copy each value over, which is what options B and C are doing.
38 |
39 | Keep in mind that methods B and C are making **shallow copies**. This works in the example because all the values are strings. If `mainArray` had objects nested within it, the objects wouldn't be cloned; rather, both the original array and the cloned array would be holding a reference to the same object, so a change to the object in one array would result in a change to the object in the other array.
40 |
41 | Remember, JavaScript passes by reference, not value. If you'd like to learn more about arrays and how to create shallow copies (like this example shows), check out the [MDN Array Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)
42 |
--------------------------------------------------------------------------------
/content/questions/reduce-object/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Reduce Object
3 | tags:
4 | - reduce
5 | - array
6 | order: 39
7 | date: '2019-09-22'
8 | answers:
9 | - 'hello // correct'
10 | - 'eohll'
11 | - 'Order not guaranteed'
12 | ---
13 |
14 | Consider the following code block. What gets logged?
15 |
16 | ```javascript
17 | const scrambled = { 2: "e", 5: "o", 1: "h", 4: "l", 3: "l" };
18 |
19 | const result = Object
20 | .values(scrambled)
21 | .reduce((agg, el) => agg + el, "");
22 |
23 | console.log(result);
24 | ```
25 |
26 |
27 |
28 | `Object.values` iterates through enumerable integer keys starting from 0 in sequential order. This is the reason why the letters appear to sort themselves correctly. (Very recently, it [*used*](https://stackoverflow.com/q/30076219) to be the case that `Object.values` did not guarantee the order of iteration over properties, but this is [no longer the case](https://github.com/tc39/proposal-for-in-order), as of December 2019.)
29 |
30 | The reduce method then takes two arguments: a reducer function and an initial value.
31 | - In this case, our reducer function is `(agg, el) => agg + el` and our initial value is `""`.
32 | - In the reducer function, `agg` is the aggregator (which starts at the initial value) and `el` is an element in the array being iterated over. In this case, as we iterate through the array, we add the current `el` to the aggregated value.
33 | - If our array was `['a', 'b', 'c']`, then the aggregator would be `a` after the first iteration, `ab` the second time, and finally would return `abc`.
34 |
--------------------------------------------------------------------------------
/content/questions/object-clone-assign-mutation/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Object Cloning (Object.assign) Comparison
3 | tags:
4 | - object
5 | - cloning
6 | - mutation
7 | order: 30
8 | date: '2019-10-05'
9 | answers:
10 | - 'Joe Nested aReturn'
11 | - 'Bob Changed bReturn'
12 | - 'Joe Changed aReturn // correct'
13 | - 'Bob Nested bReturn'
14 | ---
15 |
16 | Consider objects `a` and `b` below. What gets logged?
17 |
18 | ```javascript
19 | const a = {
20 | stringField: 'Joe',
21 | nestedField: {field: 'Nested'},
22 | functionField: () => 'aReturn'
23 | };
24 | const b = Object.assign({}, a);
25 | b.stringField = 'Bob';
26 | b.nestedField.field = 'Changed';
27 | b.functionField = () => 'bReturn';
28 | console.log(
29 | a.stringField,
30 | a.nestedField.field,
31 | a.functionField()
32 | );
33 | ```
34 |
35 |
36 |
37 | `b = Object.assign({}, a);` will create a shallow copy of object `a` and assign it to `b`. Since `b` is a shallow copy, any values in `b` of the type "object", including Date objects, will be referring to the same object that exists in the original `a` - a change to one of those in either `a` or `b` will result in the other object being changed as well, because they're the same reference.
38 |
39 | Note that, unlike using `JSON.parse` and `JSON.stringify` to deep clone an object, `Object.assign` will properly clone values on the top level of an object which can't be represented in JSON, such as functions and symbols. See [MDN Description](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Examples) for a more detailed explanation.
40 |
--------------------------------------------------------------------------------
/content/questions/object-clone-stringify/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Object Cloning (JSON.parse + JSON.stringify) Comparison
3 | tags:
4 | - object
5 | - cloning
6 | order: 28
7 | date: '2019-10-05'
8 | answers:
9 | - 'true true true true'
10 | - 'true true true false'
11 | - 'true true false true // correct'
12 | - 'false false false false'
13 | ---
14 |
15 | Consider objects `a` and `b` below. What gets logged?
16 |
17 | ```javascript
18 | const a = {
19 | stringField: 'Joe',
20 | numberField: 123,
21 | dateField: new Date('1995-12-17T03:24:00'),
22 | nestedField: {field: 'Nested'}
23 | };
24 | const b = JSON.parse(JSON.stringify(a));
25 | console.log(
26 | a.stringField === b.stringField,
27 | a.numberField === b.numberField,
28 | a.dateField === b.dateField,
29 | a.nestedField.field === b.nestedField.field
30 | );
31 | ```
32 |
33 |
34 |
35 | Setting `b = JSON.parse(JSON.stringify(a))` will perform a deep copy of object `a`. All primitive JavaScript types (Boolean, String, and Number) will be copied correctly, as will plain objects and arrays. However, non-valid JSON values (undefined, Date, Function, and other class instances) will not be copied correctly. In this instance, `JSON.stringify` will convert the Date object into an ISO string and it will remain a string when the stringified JSON is re-parsed. Since the two fields are not the same type (one is a string, the other is a Date object), the `===` will evaluate to `false`. See [MDN Description](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#Description) for a more detailed explanation.
36 |
--------------------------------------------------------------------------------
/content/questions/implicit-semicolon/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Implicit semicolon insertion
3 | tags:
4 | - semicolon
5 | - implicit
6 | - print
7 | order: 58
8 | date: Thu Oct 24 2019 16:09:25 GMT+0200 (Central European Summer Time)
9 | answers:
10 | - 'Giovanni'
11 | - 'Good morning, Giovanni'
12 | - 'Good morning,'
13 | - 'undefined // correct'
14 | ---
15 |
16 | What does this snippet of code return?
17 |
18 | ```javascript
19 | function Greetings(name) {
20 | return
21 | "Good morning, " + name
22 | }
23 |
24 | Greetings("Giovanni")
25 | ```
26 |
27 |
28 |
29 | There are a number of keywords and syntax constructions which are not permitted to have newlines at a particular point. For example, `return`, `continue`, `break`, `throw`, and `yield`, if connected with another JavaScript token on the right-hand side, are forbidden to be separated from that token by a newline. For example, when `throw`ing something, the start of the thrown expression must be on the same line as the `throw`.
30 |
31 | When the interpreter is parsing JavaScript text and comes across one of these situations where a newline is forbidden, but a newline is found, and the preceding token (`return`, `continue`, etc) does *not* end with a semicolon, a semicolon will be inserted. So, the interpreter parses the code above into:
32 |
33 | ```javascript
34 | function Greetings(name) {
35 | return;
36 | "Good morning, " + name;
37 | }
38 |
39 | Greetings("Giovanni");
40 | ```
41 |
42 | Nothing is returned, so the return value is `undefined`.
43 |
44 | For more information about the rules for Automatic Semicolon Insertion, see [this question](https://stackoverflow.com/a/2846298).
45 |
--------------------------------------------------------------------------------
/content/questions/this-keyword/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: this Keyword
3 | tags:
4 | - this
5 | order: 59
6 | date: '2019-10-14'
7 | answers:
8 | - 'myFunction'
9 | - 'Window // correct'
10 | - 'undefined'
11 | ---
12 |
13 | When running JavaScript in the browser, what gets logged when we try to call `myFunction()`?
14 |
15 | ```javascript
16 | function myFunction() {
17 | console.log(this);
18 | }
19 | myFunction();
20 | ```
21 |
22 |
23 |
24 | In this case, `this` references the window. Why? Because `myFunction` was not called on an object, nor was a particular `this` set via `.bind` or `.call`. It's a plain standalone function which was invoked without a calling context, so inside it, `this` will refer to the global object (which is the `window`). (If we were in strict mode instead, the value of `this` when there is no calling context is `undefined`.)
25 |
26 | A function will have a `this` value other than the `window` or `undefined` when one of the following occurs:
27 |
28 | * The function is called as a property of an object, eg `myObj.myFn()` will call `myFn` with a `this` value of `myObj`.
29 | * The function's `this` was bound to a particular object with `.bind` - eg `const boundFn = myFn.bind(obj); boundFn();` will result in `myFn` being called with a `this` value of `obj`.
30 | * The function was invoked via `.call`. Eg `myFn.call(obj)` will result in `myFn` being called with a `this` value of `obj`.
31 |
32 | These are all applicable to full-fledged `function`s only - arrow functions, in contrast, always have their `this` inherit from the parent block.
33 |
34 | A `this` value can't be set by assignment during execution, and it may be different each time the function is called.
35 |
--------------------------------------------------------------------------------
/src/utils/filterPosts.js:
--------------------------------------------------------------------------------
1 | import { getPersistedAnswer } from './persistAnswers';
2 |
3 | export const filterPosts = (posts = [], filterValue) => {
4 | switch (filterValue) {
5 | case 'All':
6 | return posts;
7 | case 'Correct':
8 | return posts.filter(({ node }) => {
9 | const title =
10 | node.frontmatter.title || node.fields.slug;
11 | const {
12 | selectedAnswer,
13 | correctAnswer
14 | } = getPersistedAnswer(title);
15 | return (
16 | selectedAnswer !== null &&
17 | selectedAnswer === correctAnswer
18 | );
19 | });
20 | case 'Incorrect':
21 | return posts.filter(({ node }) => {
22 | const title =
23 | node.frontmatter.title || node.fields.slug;
24 | const {
25 | selectedAnswer,
26 | correctAnswer
27 | } = getPersistedAnswer(title);
28 | return (
29 | selectedAnswer !== null &&
30 | selectedAnswer !== correctAnswer
31 | );
32 | });
33 | case 'Completed':
34 | return posts.filter(({ node }) => {
35 | const title =
36 | node.frontmatter.title || node.fields.slug;
37 | const { selectedAnswer } = getPersistedAnswer(
38 | title
39 | );
40 | console.log(selectedAnswer);
41 | return selectedAnswer !== null;
42 | });
43 | case 'Incomplete':
44 | return posts.filter(({ node }) => {
45 | const title =
46 | node.frontmatter.title || node.fields.slug;
47 | const { selectedAnswer } = getPersistedAnswer(
48 | title
49 | );
50 | return selectedAnswer === null;
51 | });
52 | default:
53 | return posts;
54 | }
55 | };
56 |
--------------------------------------------------------------------------------
/gatsby-node.js:
--------------------------------------------------------------------------------
1 | const path = require(`path`);
2 | const {
3 | createFilePath
4 | } = require(`gatsby-source-filesystem`);
5 |
6 | exports.createPages = async ({ graphql, actions }) => {
7 | const { createPage } = actions;
8 |
9 | const questionTemplate = path.resolve(
10 | `./src/templates/question.js`
11 | );
12 | const result = await graphql(
13 | `
14 | {
15 | allMarkdownRemark(
16 | sort: {
17 | fields: [frontmatter___order]
18 | order: ASC
19 | }
20 | limit: 1000
21 | ) {
22 | edges {
23 | node {
24 | fields {
25 | slug
26 | }
27 | frontmatter {
28 | title
29 | date
30 | }
31 | }
32 | }
33 | }
34 | }
35 | `
36 | );
37 |
38 | if (result.errors) {
39 | throw result.errors;
40 | }
41 |
42 | // Create question pages.
43 | const questions = result.data.allMarkdownRemark.edges;
44 |
45 | questions.forEach((question, index) => {
46 | const previous =
47 | index === questions.length - 1
48 | ? null
49 | : questions[index + 1].node;
50 | const next =
51 | index === 0 ? null : questions[index - 1].node;
52 |
53 | createPage({
54 | path: question.node.fields.slug,
55 | component: questionTemplate,
56 | context: {
57 | slug: question.node.fields.slug,
58 | previous,
59 | next
60 | }
61 | });
62 | });
63 | };
64 |
65 | exports.onCreateNode = ({ node, actions, getNode }) => {
66 | const { createNodeField } = actions;
67 |
68 | if (node.internal.type === `MarkdownRemark`) {
69 | const value = createFilePath({ node, getNode });
70 | createNodeField({
71 | name: `slug`,
72 | node,
73 | value
74 | });
75 | }
76 | };
77 |
--------------------------------------------------------------------------------
/content/questions/hoisting-race-to-the-top/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Hoisting
3 | tags:
4 | - hoisting
5 | order: 25
6 | date: '2019-10-03'
7 | answers:
8 | - 'second 1 3'
9 | - 'first 3 2 // correct'
10 | - 'second 3 3'
11 | - 'first 3 3'
12 | ---
13 |
14 | Consider the following declarations and expression. What gets logged?
15 |
16 | ```javascript
17 | immaBeOnTop();
18 |
19 | var immaBeOnTop;
20 |
21 | function immaBeOnTop() {
22 | console.log('first');
23 | }
24 |
25 | immaBeOnTop = function() {
26 | console.log('second');
27 | };
28 | ```
29 |
30 | What gets logged here?
31 |
32 | ```javascript
33 | foo();
34 |
35 | function foo() {
36 | console.log(1);
37 | }
38 |
39 | var foo = function() {
40 | console.log(2);
41 | };
42 |
43 | function foo() {
44 | console.log(3);
45 | }
46 |
47 | foo();
48 | ```
49 |
50 |
51 |
52 | The answer is `first` for the first question. While both function declarations and variable declarations are hoisted, function declarations are hoisted first and then variables. Duplicate var declarations (but not asssignments!) are also ignored. So, what is interpreted by the engine is:
53 |
54 | ```javascript
55 | function immaBeOnTop() {
56 | console.log('first');
57 | }
58 |
59 | immaBeOnTop(); //'first'
60 |
61 | immaBeOnTop = function() {
62 | console.log('second');
63 | };
64 | ```
65 |
66 | The answer is `3 2` for the second question. While duplicate var declarations are ignored, subsequent function declarations and variable assignments do override previous ones. So what's happening with the code above is:
67 |
68 | ```javascript
69 | function foo() {
70 | console.log(1);
71 | }
72 |
73 | function foo() {
74 | console.log(3);
75 | }
76 |
77 | foo(); //3
78 |
79 | foo = function() {
80 | console.log(2);
81 | };
82 |
83 | foo(); //2
84 | ```
85 |
86 | [Reference: You Don't Know JS Yet: Scope & Closures by Kyle Simpson](https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/scope-closures/ch4.md)
87 |
--------------------------------------------------------------------------------
/src/components/modal.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Modal from 'react-modal';
3 |
4 | const customStyles = {
5 | content: {
6 | top: '50%',
7 | left: '50%',
8 | right: 'auto',
9 | bottom: 'auto',
10 | marginRight: '-50%',
11 | transform: 'translate(-50%, -50%)',
12 | maxWidth: '600px'
13 | }
14 | };
15 |
16 | Modal.setAppElement('#___gatsby');
17 |
18 | const AboutModal = props => {
19 | return (
20 |
26 |
Why I Make These Quizzes
27 |
28 | These quizzes are intended to be fun ways to test your JavaScript
29 | knowledge. Many of them are tricky and dive into subjects that tripped
30 | me up when I was first learning the language. I find the concepts
31 | underlying each of these questions to be important to know as a
32 | JavaScript developer.
33 |
34 |
35 | Also, and fairly importantly, I'm considered a senior developer and
36 | would probably have trouble with a lot of these questions had I not made
37 | them myself. Please don't be hard on yourself as you attempt these
38 | questions; we're all still learning!
39 |
57 | Are you sure you want to clear your answer for this question?
58 |
59 |
60 |
61 |
62 | )
63 | }
64 |
65 | export{AboutModal,ClearAnswerModal}
--------------------------------------------------------------------------------
/content/questions/array-length-alias-default-value/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: String Operations and Array Destructuring
3 | tags:
4 | - string
5 | - destructuring
6 | order: 27
7 | date: '2019-10-05'
8 | answers:
9 | - '"quiz"'
10 | - '"typeofnan"'
11 | - '"dev" // correct'
12 | - 'undefined'
13 | - 'An error is thrown'
14 | ---
15 |
16 | In the following example, we attempt to get part of our URL's domain name. What ends up being logged?
17 |
18 | ```javascript
19 | const url = 'quiz.typeofnan.dev';
20 | const { length: ln, [ln - 1]: domain = 'quiz' } = url
21 | .split('.')
22 | .filter(Boolean);
23 | console.log(domain);
24 | ```
25 |
26 |
27 |
28 | This question applies a number of different concepts surrounding object destructuring! Let's take it one piece at a time.
29 |
30 | The following code simply assigns the string `quiz.typeofnan.dev` to the variable `url`.
31 |
32 | ```javascript
33 | const url = 'quiz.typeofnan.dev';
34 | ```
35 |
36 | The next line is where a lot of the action happens. It's generally best to first consider what's happening on the right side of the assignment, so let's first consider the following code:
37 |
38 | ```javascript
39 | url.split('.').filter(Boolean);
40 | ```
41 |
42 | `url.split('.')` will split our `url` string by the `.` character, resulting in the following array: `['quiz', 'typeofnan', 'dev']`. Applying `filter(Boolean)` on this array is the same as `filter(el => Boolean(el))`. Since all of the elements are truthy, `Boolean(el)` will always be `true`, meaning we don't actually filter anything out.
43 |
44 | The next bit applies object destructuring. Since our array is indeed an object, this is allowed.
45 |
46 | ```javascript
47 | const { length: ln, [ln - 1]: domain = 'quiz' } = [
48 | 'quiz',
49 | 'typeofnan',
50 | 'dev'
51 | ];
52 | ```
53 |
54 | In this destructuring, we use _aliasing_ to assign the array's `length` property to a variable we call `ln`. Next, we use aliasing again to assign the `ln - 1`th element to the `domain` variable. The `= 'quiz'` is a default value, meaning `domain` will equal `'quiz'` if there is no `ln - 1`th array element.
55 |
56 | Applying this to our array, `length`, which we assign to `ln`, is `3`, `ln - 1` is `2`, and the item at index `2` of our array is `dev`. Therefore, the answer is `dev`!
57 |
--------------------------------------------------------------------------------
/src/components/seo.js:
--------------------------------------------------------------------------------
1 | /**
2 | * SEO component that queries for data with
3 | * Gatsby's useStaticQuery React hook
4 | *
5 | * See: https://www.gatsbyjs.org/docs/use-static-query/
6 | */
7 |
8 | import React from 'react';
9 | import PropTypes from 'prop-types';
10 | import Helmet from 'react-helmet';
11 | import { useStaticQuery, graphql } from 'gatsby';
12 |
13 | function SEO({ description, lang, meta, title }) {
14 | const { site } = useStaticQuery(
15 | graphql`
16 | query {
17 | site {
18 | siteMetadata {
19 | title
20 | description
21 | author
22 | }
23 | }
24 | }
25 | `
26 | );
27 |
28 | const metaDescription =
29 | description || site.siteMetadata.description;
30 |
31 | return (
32 |
78 | );
79 | }
80 |
81 | SEO.defaultProps = {
82 | lang: `en`,
83 | meta: [],
84 | description: ``
85 | };
86 |
87 | SEO.propTypes = {
88 | description: PropTypes.string,
89 | lang: PropTypes.string,
90 | meta: PropTypes.arrayOf(PropTypes.object),
91 | title: PropTypes.string.isRequired
92 | };
93 |
94 | export default SEO;
95 |
--------------------------------------------------------------------------------
/content/questions/arrays-sorting-reversing/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Arrays, Sorting, and Reversing
3 | tags:
4 | - shorthand
5 | - array
6 | order: 50
7 | date: '2019-10-08'
8 | answers:
9 | - '[1, 3, 5, 7, 25]
10 | [7, 5, 3, 25, 1]
11 | [1, 25, 3, 5, 7]
12 | [1, 25, 3, 5, 7]'
13 | - '[1, 25, 3, 5, 7]
14 | [5,1,3,7,25]'
15 | - '[1, 25, 3, 5, 7]
16 | [7, 5, 3, 25, 1]
17 | [7, 5, 3, 25, 1]
18 | [7, 5, 3, 25, 1] // correct'
19 | - 'An error is thrown'
20 | ---
21 |
22 | Consider the following two arrays and operations on them. What gets logged as a result of script execution ?
23 |
24 | ```javascript
25 | const ar = [5, 1, 3, 7, 25];
26 | const ar1 = ar;
27 | console.log(ar1.sort());
28 | (
29 | [5, 25].indexOf(ar[1]) != -1 &&
30 | console.log(ar.reverse())
31 | ) ||
32 | (
33 | ar[3] == 25 && console.log(ar)
34 | );
35 | console.log(ar1);
36 | ```
37 |
38 |
39 |
40 | `const ar1 = ar` means that `ar1` points to the same array in memory as `ar`. `ar1.sort()` works **in-place** and therefore modifies the original array `ar`. **Both** variables `ar` and `ar1` point to the same sorted array.
41 |
42 | Remember that the default [sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) function converts elements to strings and then sorts alphabetically, so the first `console.log` outputs `[1, 25, 3, 5, 7]`.
43 |
44 | Next, `ar[1]` is found in the array `[5, 25]`, resulting in `[5, 25].indexOf(ar[1]) != -1` evaluating to `true`, leading to the second part of the statement (`ar.reverse()`) being evaluated. Because `ar.reverse()` also works **in-place** and modifies the original array, `ar` is now `[7, 5, 3, 25, 1]`, which is the output of the second `console.log`.
45 |
46 | Because `console.log` returns `undefined`, the first part effectively now evaluates to the following:
47 |
48 | ```javascript
49 | (
50 | undefined
51 | ) || (ar[3] == 25 && console.log(ar));
52 | ```
53 |
54 | Because `undefined` is falsy, the second half of the statement is now evaluated. `ar[3] == 25` is true because the fourth element of the array is `25`, so this statement evaluates to `true` and `ar` is outputted in the third `console.log` as `[7, 5, 3, 25, 1]`.
55 |
56 | Finally, we know that `ar1` is still pointing to the same array in memory as `ar`, so the fourth log `console.log(ar1);` simply outputs the same array again (`[7, 5, 3, 25, 1]`).
57 |
--------------------------------------------------------------------------------
/content/questions/closure-and-hoisting/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Closure and Hoisting
3 | tags:
4 | - closure
5 | - hoisting
6 | order: 58
7 | date: Mon Oct 21 2019 22:49:13 GMT-0600 (Mountain Daylight Time)
8 | answers:
9 | - 'undefined ERROR 42'
10 | - '24 ERROR 24'
11 | - '24 24 42 // correct'
12 | - 'undefined ERROR 24'
13 | - '24 Error 42'
14 | ---
15 |
16 | What would be the output of the following three `console.log`s?
17 |
18 | ```javascript
19 | function withVar() {
20 | const b = () => a;
21 | var a = 24;
22 | return b;
23 | }
24 |
25 | function withLet() {
26 | const b = () => a;
27 | let a = 24;
28 | return b;
29 | }
30 |
31 | function changingValue() {
32 | let a = 24;
33 | const b = () => a;
34 | a = 42;
35 | return b;
36 | }
37 |
38 | console.log(withVar()()); // ??
39 | console.log(withLet()()); // ??
40 | console.log(changingValue()()); // ??
41 | ```
42 |
43 |
44 | Definition: A "closure" is said to occur when a function remembers and accesses its lexical scope, even when it is executed outside of that scope. [Definition by Kyle Simpson in YDKJS](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/scope%20%26%20closures/ch5.md).
45 |
46 | When the internal functions `b` are returned from all the three functions, each function `b` gets a "closure" over the value of `a` defined in its parent function's scope. However, the value of `a` closed over by `b` in all cases is the "latest" value of `a`, or in other words, `b` has closure over the variable `a` itself, not its value. Hence, even when the value of `a` is changed, `b` always has the most recent value assigned to `a`.
47 |
48 | That is why, in `withVar`, even though `a` is undefined when `b` is first defined, however, by the time `b` is executed (inside the `console.log`), the value of `a` has been updated to `24`, and that is what is returned by `b` . Similarly, in `withLet`, the `a` variable is no longer in the "Temporal Dead Zone" by the time `b` is executed. And finally, the "updated" value of `a` is returned by `changingValue`.
49 |
50 | This example also demonstrates that the code inside a JS function does not "run" till the function is actually invoked (by using the parens, like `withVar()`). That is why, in `withVar` and `withLet`, even though function `b` returns `a`, which at that line is not declared at all. But the code actually only runs when `b` is invoked in their respective `console.log`s.
51 |
--------------------------------------------------------------------------------
/content/questions/curly-q/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Curly Q
3 | tags:
4 | - functions
5 | - brackets
6 | order: 39
7 | date: '2019-10-06'
8 | answers:
9 | - '{ foo: "foo" } undefined // correct'
10 | - 'undefined { bar: "bar" }'
11 | - 'undefined undefined'
12 | ---
13 |
14 | What will the `foo()` and `bar()` functions return when logged to the console together?
15 |
16 | ```javascript
17 | const foo = () => {
18 | return {
19 | foo: "foo"
20 | };
21 | }
22 |
23 | const bar = () => {
24 | return
25 | {
26 | bar: "bar"
27 | }
28 | }
29 |
30 | console.log(foo(), bar())
31 | ```
32 |
33 |
34 |
35 | Although the `foo()` and `bar()` functions above look almost identical, `bar()` returns
36 | `undefined`. This is because JavaScript automatically inserts semicolons after
37 | certain statements when they are followed by a newline, including `return` statements.
38 |
39 | Let's look at both functions and see where JavaScript inserts semicolons:
40 |
41 | ```javascript
42 | const foo = () => {
43 | return {
44 | foo: "foo"
45 | };
46 | }
47 | ```
48 |
49 | Hmm...the return statement is followed immediately by a curly brace on the same
50 | line, so JavaScript only adds semicolons after the closing curly braces in `foo()`, like
51 | so:
52 |
53 | ```javascript
54 | const foo = () => {
55 | return {
56 | foo: "foo"
57 | };
58 | };
59 | ```
60 |
61 | However, `bar()` is a little different.
62 |
63 | ```javascript
64 | const bar = () => {
65 | return;
66 | {
67 | bar: "bar"
68 | }
69 | };
70 | ```
71 |
72 | Note how the curly brace after `return` occurs on the following line. When
73 | `bar()` is run, JavaScript
74 | automatically places a semicolon after `return`, like so:
75 |
76 | ```javascript
77 | const bar = () => {
78 | return;
79 | {
80 | bar: "bar"
81 | }
82 | };
83 | ```
84 |
85 | It's essentially the same as running this function:
86 |
87 | ```javascript
88 | const bar = () => {
89 | return;
90 | };
91 | ```
92 |
93 | `bar` thus returns `undefined` because (according to JavaScript) it contains no
94 | inner values when run. This is a good reason to be careful about where you place
95 | brackets!
96 |
97 | (For a quick overview on
98 | JavaScript's automatic semicolon insertion, check
100 | out this article by Flavio Copes.)
101 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "typeofnan-javascript-quizzes",
3 | "private": true,
4 | "description": "JavaScript quiz questions and explanations!",
5 | "version": "0.1.0",
6 | "author": "Nick Scialli",
7 | "bugs": {
8 | "url": "https://github.com/nas5w/typeofnan-javascript-quizzes/issues"
9 | },
10 | "dependencies": {
11 | "gatsby": "^2.15.14",
12 | "gatsby-image": "^2.2.18",
13 | "gatsby-plugin-feed": "^2.3.12",
14 | "gatsby-plugin-google-analytics": "^2.1.16",
15 | "gatsby-plugin-manifest": "^2.2.16",
16 | "gatsby-plugin-node-fields": "^2.0.1",
17 | "gatsby-plugin-offline": "^2.2.10",
18 | "gatsby-plugin-react-helmet": "^3.1.7",
19 | "gatsby-plugin-sharp": "^2.2.21",
20 | "gatsby-plugin-sitemap": "^2.2.16",
21 | "gatsby-plugin-typography": "^2.3.7",
22 | "gatsby-plugin-web-font-loader": "^1.0.4",
23 | "gatsby-remark-copy-linked-files": "^2.1.19",
24 | "gatsby-remark-images": "^3.1.21",
25 | "gatsby-remark-prismjs": "^3.3.13",
26 | "gatsby-remark-responsive-iframe": "^2.2.16",
27 | "gatsby-remark-smartypants": "^2.1.8",
28 | "gatsby-source-filesystem": "^2.1.22",
29 | "gatsby-transformer-remark": "^2.6.22",
30 | "gatsby-transformer-sharp": "^2.2.14",
31 | "prism-themes": "^1.1.0",
32 | "prismjs": "^1.27.0",
33 | "react": "^16.9.0",
34 | "react-dom": "^16.9.0",
35 | "react-github-btn": "^1.0.6",
36 | "react-helmet": "^5.2.1",
37 | "react-modal": "^3.10.1",
38 | "react-typography": "^0.16.19",
39 | "semantic-ui-css": "^2.4.1",
40 | "semantic-ui-react": "^0.88.1",
41 | "typeface-merriweather": "0.0.72",
42 | "typeface-montserrat": "0.0.75",
43 | "typography": "^0.16.19",
44 | "typography-theme-wordpress-2016": "^0.16.19"
45 | },
46 | "devDependencies": {
47 | "lodash.template": "^4.5.0",
48 | "prettier": "^1.18.2"
49 | },
50 | "homepage": "https://quiz.typeofnan.dev/",
51 | "keywords": [
52 | "gatsby",
53 | "javascript"
54 | ],
55 | "license": "MIT",
56 | "main": "n/a",
57 | "repository": {
58 | "type": "git",
59 | "url": "https://github.com/nas5w/typeofnan-javascript-quizzes.git"
60 | },
61 | "scripts": {
62 | "build": "gatsby build",
63 | "develop": "gatsby develop",
64 | "format": "prettier --write \"**/*.{js,jsx,json,md}\"",
65 | "new-question": "node ./scripts/new-question/index.js",
66 | "start": "yarn run develop",
67 | "serve": "gatsby serve",
68 | "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing \""
69 | },
70 | "engines": {
71 | "yarn": "^1.17.0",
72 | "node": ">=6.11.5"
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/content/questions/typeof-nan/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Typeof NaN
3 | tags:
4 | - number
5 | - operator
6 | - comparison
7 | - equality
8 | - type coercion
9 | - operation precedence
10 | order: 72
11 | date: Thu Jun 25 2020 12:16:01 GMT+0100 (West Africa Standard Time)
12 | answers:
13 | - 'false, "2number", true, "apple"'
14 | - 'true, "2number", false, "orange"'
15 | - 'false, "NaNnumber", false, "orange" // correct'
16 | - 'true, "NaNnumber", true, "apple"'
17 | ---
18 |
19 | Looking at the code below, what would be logged?
20 |
21 | ```js
22 | console.log(parseInt('a123') == Number("123z"));
23 |
24 | console.log(typeof "10"/5 + typeof NaN);
25 |
26 | console.log(isNaN(("10"/5)));
27 |
28 | console.log(typeof (50 + +"100px") === "number" ? "orange" : "apple");
29 |
30 | ```
31 |
32 |
33 |
34 | In the first log, both `parseInt()` and `Number()` would return `NaN` as these strings can't be parsed into numbers. This would result in
35 |
36 | ```js
37 | console.log(NaN == NaN)
38 | ```
39 |
40 | since `NaN` can never equal `NaN`, `false` is logged.
41 |
42 | In the second log, `typeof "10"/5` returns `NaN` because of operator precedence.
43 |
44 | Since the `typeof` operator has a higher precedence than the divide operator `/`, we evaluate `typeof "10"` which returns `"string"`, we then have `"string"/5`, which results in `NaN`.
45 |
46 | `typeof NaN` returns the string `"number". Therefore, the concatenated output `"NaNnumber"`.
47 |
48 | ```js
49 | console.log( typeof "10"/5 + typeof NaN);
50 | console.log( "string"/5 + "number")
51 | console.log( NaN + "number")
52 | console.log( "NaNnumber")
53 | ```
54 |
55 | You can read more about operator precedence [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence)
56 |
57 | In the third log, `"10"/5` would return `2` because of type coercion and since `2` is not equal to `NaN`, the output is false
58 |
59 | ```js
60 | console.log(isNaN( ("10"/5) ));
61 | console.log(isNaN(2));
62 | console.log( false );
63 | ```
64 |
65 | The fourth log, first converts `"100px"` to `NaN` as the `+` operator forces a string to convert to number
66 |
67 | ```js
68 | console.log( typeof (50 + +"100px") === "number" ? "orange" : "apple" );
69 | console.log( typeof (50 + NaN) === "number" ? "orange" : "apple" );
70 | ```
71 |
72 | Since `NaN` propagates, any operation done with `NaN` leads to `NaN`, `50 + NaN` equals `NaN`
73 |
74 | ```js
75 | console.log( typeof (NaN) === "number" ? "orange" : "apple" );
76 | ```
77 |
78 | since `typeof NaN` returns `"number"` it resolves to true and returns `"orange"`.
79 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |