Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func();

In this example we can observe the peculiar difference between a "non-existing" and "uninitialized" variable.

As you may have read in the article [](info:closure), a variable starts in the "uninitialized" state from the moment when the execution enters a code block (or a function). And it stays uninitalized until the corresponding `let` statement.
As you may have read in the article [](info:closure), a variable starts in the "uninitialized" state from the moment when the execution enters a code block (or a function). And it stays uninitialized until the corresponding `let` statement.

In other words, a variable technically exists, but can't be used before `let`.

Expand Down
4 changes: 2 additions & 2 deletions 1-js/09-classes/03-static-properties-methods/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,8 @@ How does it work? Again, using prototypes. As you might have already guessed, `e

So, `Rabbit extends Animal` creates two `[[Prototype]]` references:

1. `Rabbit` function prototypally inherits from `Animal` function.
2. `Rabbit.prototype` prototypally inherits from `Animal.prototype`.
1. `Rabbit` function prototypically inherits from `Animal` function.
2. `Rabbit.prototype` prototypically inherits from `Animal.prototype`.

As a result, inheritance works both for regular and static methods.

Expand Down
2 changes: 1 addition & 1 deletion 1-js/11-async/02-promise-basics/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ The idea of `finally` is to set up a handler for performing cleanup/finalizing a

E.g. stopping loading indicators, closing no longer needed connections, etc.

Think of it as a party finisher. Irresepective of whether a party was good or bad, how many friends were in it, we still need (or at least should) do a cleanup after it.
Think of it as a party finisher. Irrespective of whether a party was good or bad, how many friends were in it, we still need (or at least should) do a cleanup after it.

The code may look like this:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ function customPromiseAll(promises) {
results[index] = result;
resultsCount++;
if (resultsCount === promises.length) {
resolve(results); // when all results are ready - successs
resolve(results); // when all results are ready - success
}
})
.catch(error => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,4 @@ function clockStop() {

Please note that the call to `update()` is not only scheduled in `clockStart()`, but immediately run in the line `(*)`. Otherwise the visitor would have to wait till the first execution of `setInterval`. And the clock would be empty till then.

Also it is important to set a new interval in `clockStart()` only when the clock is not running. Otherways clicking the start button several times would set multiple concurrent intervals. Even worse - we would only keep the `timerID` of the last interval, losing references to all others. Then we wouldn't be able to stop the clock ever again! Note that we need to clear the `timerID` when the clock is stopped in the line `(**)`, so that it can be started again by running `clockStart()`.
Also it is important to set a new interval in `clockStart()` only when the clock is not running. Otherwise clicking the start button several times would set multiple concurrent intervals. Even worse - we would only keep the `timerID` of the last interval, losing references to all others. Then we wouldn't be able to stop the clock ever again! Note that we need to clear the `timerID` when the clock is stopped in the line `(**)`, so that it can be started again by running `clockStart()`.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ let sortedRows = Array.from(table.tBodies[0].rows) // 1
table.tBodies[0].append(...sortedRows); // (3)
```

The step-by-step algorthm:
The step-by-step algorithm:

1. Get all `<tr>`, from `<tbody>`.
2. Then sort them comparing by the content of the first `<td>` (the name field).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ Differences:
1. `clientWidth` is numeric, while `getComputedStyle(elem).width` returns a string with `px` at the end.
2. `getComputedStyle` may return non-numeric width like `"auto"` for an inline element.
3. `clientWidth` is the inner content area of the element plus paddings, while CSS width (with standard `box-sizing`) is the inner content area *without paddings*.
4. If there's a scrollbar and the browser reserves the space for it, some browser substract that space from CSS width (cause it's not available for content any more), and some do not. The `clientWidth` property is always the same: scrollbar size is substracted if reserved.
4. If there's a scrollbar and the browser reserves the space for it, some browser substract that space from CSS width (cause it's not available for content any more), and some do not. The `clientWidth` property is always the same: scrollbar size is subtracted if reserved.
2 changes: 1 addition & 1 deletion 2-ui/2-events/02-bubbling-and-capturing/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ elem.addEventListener("click", e => alert(2));
````

```smart header="The `event.stopPropagation()` during the capturing also prevents the bubbling"
The `event.stopPropagation()` method and its sibling `event.stopImmediatePropagation()` can also be called on the capturing phase. Then not only the futher capturing is stopped, but the bubbling as well.
The `event.stopPropagation()` method and its sibling `event.stopImmediatePropagation()` can also be called on the capturing phase. Then not only is the further capturing stopped, but the bubbling as well.

In other words, normally the event goes first down ("capturing") and then up ("bubbling"). But if `event.stopPropagation()` is called during the capturing phase, then the event travel stops, no bubbling will occur.
```
Expand Down
2 changes: 1 addition & 1 deletion 2-ui/3-event-details/7-keyboard-events/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ To reliably track layout-dependent characters, `event.key` may be a better way.

On the other hand, `event.code` has the benefit of staying always the same, bound to the physical key location. So hotkeys that rely on it work well even in case of a language switch.

Do we want to handle layout-dependant keys? Then `event.key` is the way to go.
Do we want to handle layout-dependent keys? Then `event.key` is the way to go.

Or we want a hotkey to work even after a language switch? Then `event.code` may be better.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
if (this.readyState == EventSource.CONNECTING) {
log(`Reconnecting (readyState=${this.readyState})...`);
} else {
log("Error has occured.");
log("Error has occurred.");
}
};

Expand Down
4 changes: 2 additions & 2 deletions 6-data-storage/03-indexeddb/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ We can also use `async/await` with the help of a promise-based wrapper, like <ht
```smart header="Where's the data?"
Technically, the data is usually stored in the visitor's home directory, along with browser settings, extensions, etc.

Different browsers and OS-level users have each their own independant storage.
Different browsers and OS-level users have each their own independent storage.
```

## Open database
Expand Down Expand Up @@ -225,7 +225,7 @@ That's a technical limitation. Outside of the handler we'll be able to add/remov
To perform a database version upgrade, there are two main approaches:

1. We can implement per-version upgrade functions: from 1 to 2, from 2 to 3, from 3 to 4 etc. Then, in `upgradeneeded` we can compare versions (e.g. old 2, now 4) and run per-version upgrades step by step, for every intermediate version (2 to 3, then 3 to 4).
2. Or we can just examine the database: get a list of existing object stores as `db.objectStoreNames`. That object is a [DOMStringList](https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#domstringlist) that provides `contains(name)` method to check for existance. And then we can do updates depending on what exists and what doesn't.
2. Or we can just examine the database: get a list of existing object stores as `db.objectStoreNames`. That object is a [DOMStringList](https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#domstringlist) that provides `contains(name)` method to check for existence. And then we can do updates depending on what exists and what doesn't.

For small databases the second variant may be simpler.

Expand Down