Skip to content
This repository has been archived by the owner on May 7, 2023. It is now read-only.

Commit

Permalink
conditional Travis Lint using prettier-eslint, prettify snippets (#59)
Browse files Browse the repository at this point in the history
* question fixes

* lint using prettier

* ignore no-unused-vars on getCodeBlocks

* fix lintweb.sh

* remove one-value parantheses rule
  • Loading branch information
Felix Wu committed May 30, 2018
1 parent b6c7063 commit ff5dde0
Show file tree
Hide file tree
Showing 34 changed files with 408 additions and 98 deletions.
9 changes: 9 additions & 0 deletions .prettierrc.js
@@ -0,0 +1,9 @@
module.exports = {
printWidth: 80,
semi: false,
useTabs: false,
tabWidth: 2,
singleQuote: false,
bracketSpacing: true,
jsxBracketSameLine: false,
}
3 changes: 2 additions & 1 deletion .travis.yml
Expand Up @@ -12,7 +12,8 @@ jobs:
- yarn install
before_script:
- chmod +x .travis/checkIfCron.sh && ./.travis/checkIfCron.sh
- yarn lint --fix
- chmod +x .travis/lintweb.sh && ./.travis/lintweb.sh
- yarn formatQuestions
- yarn extractor
- yarn builder
script:
Expand Down
6 changes: 6 additions & 0 deletions .travis/lintweb.sh
@@ -0,0 +1,6 @@
test $TRAVIS_EVENT_TYPE = push && test $TRAVIS_BRANCH = master \
&& echo -e "\e[95mMaster push, checking for script and web errors." \
&& yarn lint \
&& yarn format

exit 0
12 changes: 9 additions & 3 deletions package.json
@@ -1,14 +1,19 @@
{
"name": "30-seconds-of-interviews",
"description": "The curated collection of common interview questions to help you prepare for your next interview.",
"description":
"The curated collection of common interview questions to help you prepare for your next interview.",
"version": "0.0.1",
"main": "index.js",
"scripts": {
"builder": "node ./scripts/build.js",
"extractor": "node ./scripts/extract.js",
"dev": "parcel website/index.html",
"build": "parcel build website/index.html -d docs/ --public-url ./",
"lint": "eslint --ext md,js ."
"lint": "eslint --fix --ext js .",
"formatQuestions":
"prettier-eslint --write \"questions/*.md\" --log-level \"info\"",
"format":
"prettier-eslint --write \"scripts/*.js\" && prettier-eslint --write \"website/**/*.js\""
},
"repository": {
"type": "git",
Expand Down Expand Up @@ -41,6 +46,7 @@
"eslint-plugin-markdown": "^1.0.0-beta.6",
"eslint-plugin-react": "^7.8.2",
"node-sass": "^4.9.0",
"parcel-bundler": "^1.8.1"
"parcel-bundler": "^1.8.1",
"prettier-eslint-cli": "^4.7.1"
}
}
38 changes: 32 additions & 6 deletions questions/callback-hell.md
@@ -1,12 +1,12 @@
### How can you avoid callback hells?

```js
getData(function(a){
getMoreData(a, function(b){
getMoreData(b, function(c){
getMoreData(c, function(d){
getMoreData(d, function(e){
// ...
getData(function(a) {
getMoreData(a, function(b) {
getMoreData(b, function(c) {
getMoreData(c, function(d) {
getMoreData(d, function(e) {
// ...
})
})
})
Expand All @@ -16,6 +16,32 @@ getData(function(a){

#### Answer

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

The above code can be restructured like so:

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

Before ES2017 brought `async/await`, promise chaining was used instead (whether ES2015's native ones or a library before that):

```js
getData()
.then(getMoreData)
.then(getMoreData)
.then(getMoreData)
.then(getMoreData)
.then(...)
```

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

* modularization: break callbacks into independent functions
Expand Down
2 changes: 1 addition & 1 deletion questions/callbacks.md
Expand Up @@ -4,7 +4,7 @@

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

Event listeners are callbacks that are only executed when a specific event occurs.
As an example, event listeners are callbacks that are only executed when a specific event occurs.

```js
function onClick() {
Expand Down
8 changes: 6 additions & 2 deletions questions/closures.md
@@ -1,4 +1,4 @@
### What is a closure?
### What is a closure? Can you give a useful example of one?

#### Answer

Expand All @@ -8,11 +8,15 @@ A closure is a function defined inside another function and has access to its le
* Variables declared in the scope of the parent function
* Variables declared in the global scope

In JavaScript, all functions are closures because they have access to the outer scope, but most functions don't utilise the usefulness of closures: the persistence of state. Closures are also sometimes called stateful functions because of this.

In addition, closures are the only way to store private data that can't be accessed from the outside in JavaScript. They are the key to the UMD (Universal Module Definition) pattern, which is frequently used in libraries that only expose a public API but keep the implementation details private, preventing name collisions with other libraries or the user's own code.

#### Good to hear

* Closures are useful because they let you associate data with a function that operates on that data.
* A closure can substitute an object with only a single method.
* Closures can be used to emulate private methods.
* Closures can be used to emulate private properties and methods.

##### Additional links

Expand Down
8 changes: 4 additions & 4 deletions questions/comparing-objects.md
Expand Up @@ -27,10 +27,10 @@ function isDeepEqual(obj1, obj2, testPrototypes = false) {

const prototypesAreEqual = testPrototypes
? isDeepEqual(
Object.getPrototypeOf(obj1),
Object.getPrototypeOf(obj2),
true
)
Object.getPrototypeOf(obj1),
Object.getPrototypeOf(obj2),
true
)
: true

const obj1Props = Object.getOwnPropertyNames(obj1)
Expand Down
2 changes: 1 addition & 1 deletion questions/css-preprocessors.md
Expand Up @@ -2,7 +2,7 @@

#### Answer

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

#### Good to hear

Expand Down
2 changes: 1 addition & 1 deletion questions/css-specificity.md
Expand Up @@ -22,4 +22,4 @@ When two selectors are compared, the comparison is made on a per-column basis (e

<!-- tags: (css) -->

<!-- expertise: (1) -->
<!-- expertise: (2) -->
7 changes: 4 additions & 3 deletions questions/dom.md
Expand Up @@ -2,13 +2,14 @@

#### Answer

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

#### Good to hear

* The DOM was designed to be independent of any particular programming language, making the structural representation of the document available from a single, consistent API
* The DOM was designed to be independent of any particular programming language, making the structural representation of the document available from a single, consistent API.
* The DOM is constructed progressively in the browser as a page loads, which is why scripts are often placed at the bottom of a page, in the `<head>` with a `defer` attribute, or inside a `DOMContentLoaded` event listener. Scripts that manipulate DOM nodes should be run after the DOM has been constructed to avoid errors.
* `document.getElementById()` and `document.querySelector()` are common functions for selecting DOM nodes.
* Setting the `innerHTML` property to a new value runs the string through the HTML parser, offering an easy way to append dynamic HTML content to a node.

##### Additional links

Expand Down
6 changes: 3 additions & 3 deletions questions/double-vs-triple-equals.md
Expand Up @@ -6,9 +6,9 @@ Triple equals (`===`) checks for strict equality, which means both the type and

#### Good to hear

* Whenever possible, use triple equals to test equality because loose equality `==` can have unintuitive results
* Type coercion means the values are converted into the same type
* Mention of falsy values and their comparison
* Whenever possible, use triple equals to test equality because loose equality `==` can have unintuitive results.
* Type coercion means the values are converted into the same type.
* Mention of falsy values and their comparison.

##### Additional links

Expand Down
31 changes: 28 additions & 3 deletions questions/event-driven-programming.md
Expand Up @@ -2,12 +2,37 @@

#### Answer

Event-driven programming is building an application that is based on and responds to events. Whenever an event occurs, the application responds by running a callback function, which is registered to that event and context.
Event-driven programming is a paradigm that involves building applications that send and receive events. When the program emits events, the program responds by running any callback functions that are registered to that event and context, passing in associated data to the function. With this pattern, events can be emitted into the wild without throwing errors even if no functions are subscribed to it.

A common example of this is the pattern of elements listening to DOM events such as `click` and `mouseenter`, where a callback function is run when the event occurs.

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

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

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

With this implementation, `on` is the way to _subscribe_ to an event, while `emit` is the way to _publish_ the event.

#### Good to hear

* Responds to events that occur by running a callback function
* Follows a publish-subscribe pattern
* Follows a publish-subscribe pattern.
* Responds to events that occur by running any callback functions subscribed to the event.
* Show how to create a simple pub-sub implementation with JavaScript.

##### Additional links

Expand Down
43 changes: 36 additions & 7 deletions questions/hoisting.md
Expand Up @@ -2,20 +2,49 @@

#### Answer

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

However, the value is not hoisted with the declaration.

The following snippet:

```js
console.log(hoist)
var hoist = "value"
```

is equivalent to:

```js
var hoist
console.log(hoist)
hoist = "value"
```

Therefore logging `hoist` outputs `undefined` to the console, not `"value"`.

Hoisting also allows you to invoke a function declaration before it appears to be declared in a program.

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

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

```js
console.log(hoist) // Output: undefined
var hoist = "The variable has been hoisted."
myFunction() // Error: `myFunction` is not a function
var myFunction = function() {
console.log("hello")
}
```

#### Good to hear

* Hoisting is JavaScript’s default behavior of moving declarations to the top
* Functions are hoisted before variables
* Mention of `strict` mode
* `const` variables must be both declared and initialised before use
* `let` variables must be declared before use
* Functions declarations are hoisted before variable declarations

##### Additional links

Expand Down
2 changes: 1 addition & 1 deletion questions/html-multiple-header-footers.md
Expand Up @@ -2,7 +2,7 @@

#### Answer

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

#### Good to hear

Expand Down
2 changes: 1 addition & 1 deletion questions/html-specification-implementation.md
Expand Up @@ -9,7 +9,7 @@ A browser is said to “support” a specification if it handles valid documents
#### Good to hear

* `HTML5` defines some rules to follow for an invalid `HTML5` document (i.e., one that contains syntactical errors)
* However, invalid documents may contain anything, so it's impossible for the specification to handle all possibilities comprehensively.
* However, invalid documents may contain anything, so it's impossible for the specification to handle all possibilities comprehensively.
* Thus, many decisions about how to handle malformed documents are left up to the browser.

##### Additional links
Expand Down
2 changes: 1 addition & 1 deletion questions/html5-semantic-elements-usage.md
@@ -1,4 +1,4 @@
### Briefly describe the correct usage of the following HTML5 semantic elements: `<header>`, `<article>`,` <section>`, `<footer>`
### Briefly describe the correct usage of the following HTML5 semantic elements: `<header>`, `<article>`,`<section>`, `<footer>`

#### Answer

Expand Down
2 changes: 1 addition & 1 deletion questions/html5-web-storage.md
Expand Up @@ -18,7 +18,7 @@ Both forms of storage are scoped to the document origin so that documents with d

#### Good to hear

* Earlier, this was done with cookies.
* Earlier, this was done with cookies.
* The storage limit is far larger (at least 5MB) than with cookies and its faster.
* The data is never transferred to the server and can only be used if the client specifically asks for it.

Expand Down
8 changes: 4 additions & 4 deletions questions/wrap-content.md → questions/iife.md
@@ -1,16 +1,16 @@
### What is the reason for wrapping the entire contents of a JavaScript source file in a function?
### What is the reason for wrapping the entire contents of a JavaScript source file in a function that is immediately invoked?

#### Answer

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

```js
const myLibrary = function () {
const myLibrary = (function() {
var privateVariable = 2
return {
publicMethod: () => privateVariable
}
}()
})()
privateVariable // ReferenceError
myLibrary.publicMethod() // 2
```
Expand Down
8 changes: 4 additions & 4 deletions questions/node-error-first-callback.md
@@ -1,7 +1,7 @@
### NodeJS uses a callback pattern in many instances where if an error were returned it will pass it as the first argument to the callback. What are the advantages of this pattern?

```js
fs.readFile(filePath, function(err, data) {
fs.readFile(filePath, function(err, data) {
if (err) {
// handle the error, the return is important here
// so execution stops here
Expand All @@ -20,7 +20,7 @@ Advantages include:
* Having a consistent API leads to more adoption
* Ability to easily adapt a callback pattern that will lead to more maintainable code

As you can see from below example, the callback is called with null as its first argument if there is no error. However, if there is an error, you create an Error object, which then becomes the callback's only parameter. The callback function allows a user to easily know whether or not an error occurred.
As you can see from below example, the callback is called with null as its first argument if there is no error. However, if there is an error, you create an Error object, which then becomes the callback's only parameter. The callback function allows a user to easily know whether or not an error occurred.

This practice is also called the _Node.js error convention_, and this kind of callback implementations are called _error-first callbacks_.

Expand All @@ -33,7 +33,7 @@ var isTrue = function(value, callback) {
}
}

var callback = function (error, retval) {
var callback = function(error, retval) {
if (error) {
console.log(error)
return
Expand All @@ -42,7 +42,7 @@ var callback = function (error, retval) {
}

isTrue(false, callback)
isTrue(true, callback)
isTrue(true, callback)

/*
{ stack: [Getter/Setter],
Expand Down

0 comments on commit ff5dde0

Please sign in to comment.