Skip to content

Commit 21c93cf

Browse files
committed
merging all conflicts
2 parents 118b67d + c56e6a5 commit 21c93cf

File tree

33 files changed

+241
-128
lines changed

33 files changed

+241
-128
lines changed

1-js/02-first-steps/04-variables/2-declare-variables/solution.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ Isso é simples:
66
let ourPlanetName = "Earth";
77
```
88

9+
<<<<<<< HEAD
910
Note que poderíamos usar um nome mais curto, `planet`, mas pode não ser óbvio a que planeta se refere. É bom ser mais detalhado. Pelo menos até a variável isNotTooLong.
11+
=======
12+
Note, we could use a shorter name `planet`, but it might not be obvious what planet it refers to. It's nice to be more verbose. At least until the variable isNotTooLong.
13+
>>>>>>> c56e6a57ac3497aab77128c5bfca13513980709b
1014
1115
Em segundo lugar, o nome do visitante atual:
1216

Lines changed: 74 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
# Polyfills
2+
# Polyfills and transpilers
33

44
The JavaScript language steadily evolves. New proposals to the language appear regularly, they are analyzed and, if considered worthy, are appended to the list at <https://tc39.github.io/ecma262/> and then progress to the [specification](http://www.ecma-international.org/publications/standards/Ecma-262.htm).
55

@@ -9,23 +9,24 @@ So it's quite common for an engine to implement only the part of the standard.
99

1010
A good page to see the current state of support for language features is <https://kangax.github.io/compat-table/es6/> (it's big, we have a lot to study yet).
1111

12-
## Babel
12+
As programmers, we'd like to use most recent features. The more good stuff - the better!
1313

14-
When we use modern features of the language, some engines may fail to support such code. Just as said, not all features are implemented everywhere.
14+
From the other hand, how to make out modern code work on older engines that don't understand recent features yet?
1515

16-
Here Babel comes to the rescue.
16+
There are two tools for that:
1717

18-
[Babel](https://babeljs.io) is a [transpiler](https://en.wikipedia.org/wiki/Source-to-source_compiler). It rewrites modern JavaScript code into the previous standard.
18+
1. Transpilers.
19+
2. Polyfills.
1920

20-
Actually, there are two parts in Babel:
21+
Here, in this chapter, our purpose is to get the gist of how they work, and their place in web development.
2122

22-
1. First, the transpiler program, which rewrites the code. The developer runs it on their own computer. It rewrites the code into the older standard. And then the code is delivered to the website for users. Modern project build systems like [webpack](http://webpack.github.io/) provide means to run transpiler automatically on every code change, so that it's very easy to integrate into development process.
23+
## Transpilers
2324

24-
2. Second, the polyfill.
25+
A [transpiler](https://en.wikipedia.org/wiki/Source-to-source_compiler) is a special piece of software that can parse ("read and understand") modern code, and rewrite it using older syntax constructs, so that the result would be the same.
2526

26-
New language features may include not only syntax constructs, but also built-in functions.
27-
The transpiler rewrites the code, transforming syntax constructs into older ones. But as for new built-in functions, we need to implement them. JavaScript is a highly dynamic language, scripts may add/modify any functions, so that they behave according to the modern standard.
27+
E.g. JavaScript before year 2020 didn't have the "nullish coalescing operator" `??`. So, if a visitor uses an outdated browser, it may fail to understand the code like `height = height ?? 100`.
2828

29+
<<<<<<< HEAD
2930
There's a term "polyfill" for scripts that "fill in" the gap and add missing implementations.
3031

3132
Two interesting polyfills are:
@@ -35,24 +36,79 @@ Actually, there are two parts in Babel:
3536
So, we need to setup the transpiler and add the polyfill for old engines to support modern features.
3637

3738
If we orient towards modern engines and do not use features except those supported everywhere, then we don't need to use Babel.
39+
=======
40+
A transpiler would analyze our code and rewrite `height ?? 100` into `(height !== undefined && height !== null) ? height : 100`.
3841

39-
## Examples in the tutorial
42+
```js
43+
// before running the transpiler
44+
height = height ?? 100;
4045

46+
// after running the transpiler
47+
height = (height !== undefined && height !== null) ? height : 100;
48+
```
49+
>>>>>>> c56e6a57ac3497aab77128c5bfca13513980709b
4150
42-
````online
43-
Most examples are runnable at-place, like this:
51+
Now the rewritten code is suitable for older JavaScript engines.
4452
45-
```js run
46-
alert('Press the "Play" button in the upper-right corner to run');
47-
```
53+
Usually, a developer runs the transpiler on their own computer, and then deploys the transpiled code to the server.
54+
55+
Speaking of names, [Babel](https://babeljs.io) is one of the most prominent transpilers out there.
56+
57+
Modern project build systems, such as [webpack](http://webpack.github.io/), provide means to run transpiler automatically on every code change, so it's very easy to integrate into development process.
58+
59+
## Polyfills
4860
49-
Examples that use modern JS will work only if your browser supports it.
50-
````
61+
New language features may include not only syntax constructs and operators, but also built-in functions.
5162
63+
For example, `Math.trunc(n)` is a function that "cuts off" the decimal part of a number, e.g `Math.trunc(1.23) = 1`.
64+
65+
In some (very outdated) JavaScript engines, there's no `Math.trunc`, so such code will fail.
66+
67+
<<<<<<< HEAD
5268
```offline
5369
As you're reading the offline version, examples are not runnable. But they usually work :)
5470
```
5571
5672
[Chrome Canary](https://www.google.com/chrome/browser/canary.html) is good for all examples, but other modern browsers are mostly fine too.
5773
5874
Note that on production we can use Babel to translate the code into suitable for less recent browsers, so there will be no such limitation, the code will run everywhere.
75+
=======
76+
As we're talking about new functions, not syntax changes, there's no need to transpile anything here. We just need to declare the missing function.
77+
78+
A script that updates/adds new functions is called "polyfill". It "fills in" the gap and adds missing implementations.
79+
80+
For this particular case, the polyfill for `Math.trunc` is a script that implements it, like this:
81+
82+
```js
83+
if (!Math.trunc) { // if no such function
84+
// implement it
85+
Math.trunc = function(number) {
86+
// Math.ceil and Math.floor exist even in ancient JavaScript engines
87+
// they are covered later in the tutorial
88+
return number < 0 ? Math.ceil(number) : Math.floor(number);
89+
};
90+
}
91+
```
92+
93+
JavaScript is a highly dynamic language, scripts may add/modify any functions, even including built-in ones.
94+
95+
Two interesting libraries of polyfills are:
96+
- [core js](https://github.com/zloirock/core-js) that supports a lot, allows to include only needed features.
97+
- [polyfill.io](http://polyfill.io) service that provides a script with polyfills, depending on the features and user's browser.
98+
99+
100+
## Summary
101+
102+
In this chapter we'd like to motivate you to study modern and even "bleeding-edge" langauge features, even if they aren't yet well-supported by JavaScript engines.
103+
104+
Just don't forget to use transpiler (if using modern syntax or operators) and polyfills (to add functions that may be missing). And they'll ensure that the code works.
105+
106+
For example, later when you're familiar with JavaScript, you can setup a code build system based on [webpack](http://webpack.github.io/) with [babel-loader](https://github.com/babel/babel-loader) plugin.
107+
108+
Good resources that show the current state of support for various features:
109+
- <https://kangax.github.io/compat-table/es6/> - for pure JavaScript.
110+
- <https://caniuse.com/> - for browser-related functions.
111+
112+
P.S. Google Chrome is usually the most up-to-date with language features, try it if a tutorial demo fails. Most tutorial demos work with any modern browser though.
113+
114+
>>>>>>> c56e6a57ac3497aab77128c5bfca13513980709b

1-js/05-data-types/04-array/10-maximal-subarray/solution.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ alert( getMaxSubSum([1, 2, 3]) ); // 6
5757
alert( getMaxSubSum([100, -9, 2, -3, 5]) ); // 100
5858
```
5959

60-
The solution has a time complexety of [O(n<sup>2</sup>)](https://en.wikipedia.org/wiki/Big_O_notation). In other words, if we increase the array size 2 times, the algorithm will work 4 times longer.
60+
The solution has a time complexity of [O(n<sup>2</sup>)](https://en.wikipedia.org/wiki/Big_O_notation). In other words, if we increase the array size 2 times, the algorithm will work 4 times longer.
6161

6262
For big arrays (1000, 10000 or more items) such algorithms can lead to a serious sluggishness.
6363

1-js/05-data-types/04-array/article.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ arr.push("Pear"); // modify the array by reference
209209
alert( fruits ); // Banana, Pear - 2 items now
210210
```
211211

212-
...But what makes arrays really special is their internal representation. The engine tries to store its elements in the contiguous memory area, one after another, just as depicted on the illustrations in this chapter, and there are other optimizations as well, to make arrays work really fast.
212+
...But what makes arrays really special is their internal representation. The engine tries to store its elements in the contiguous memory area, one after another, just as depicted on the illustrations in this chapter, and there are other optimizations as well, to make arrays work really fast.
213213

214214
But they all break if we quit working with an array as with an "ordered collection" and start working with it as if it were a regular object.
215215

1-js/05-data-types/08-weakmap-weakset/article.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ alert(cache.size); // 1 (Ouch! The object is still in cache, taking memory!)
207207

208208
For multiple calls of `process(obj)` with the same object, it only calculates the result the first time, and then just takes it from `cache`. The downside is that we need to clean `cache` when the object is not needed any more.
209209

210-
If we replace `Map` with `WeakMap`, then this problem disappears. The cached result will be removed from memory automatically after the object gets garbage collected .
210+
If we replace `Map` with `WeakMap`, then this problem disappears. The cached result will be removed from memory automatically after the object gets garbage collected.
211211

212212
```js run
213213
// 📁 cache.js
@@ -284,7 +284,8 @@ The most notable limitation of `WeakMap` and `WeakSet` is the absence of iterati
284284

285285
`WeakSet` is `Set`-like collection that stores only objects and removes them once they become inaccessible by other means.
286286

287-
It's main advantages are that they have weak reference to objects, so they can easily be removed by garbage colector.
288-
That comes at the cost of not having support for `clear`, `size`, `keys`, `values` ...
287+
Their main advantages are that they have weak reference to objects, so they can easily be removed by garbage collector.
288+
289+
That comes at the cost of not having support for `clear`, `size`, `keys`, `values`...
289290

290291
`WeakMap` and `WeakSet` are used as "secondary" data structures in addition to the "primary" object storage. Once the object is removed from the primary storage, if it is only found as the key of `WeakMap` or in a `WeakSet`, it will be cleaned up automatically.

1-js/06-advanced-functions/06-function-object/5-sum-many-brackets/solution.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
Now the code:
77

8-
```js run
8+
```js demo run
99
function sum(a) {
1010

1111
let currentSum = a;

1-js/09-classes/04-private-protected-properties-methods/article.md

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,9 @@ class CoffeeMachine {
9696
_waterAmount = 0;
9797

9898
set waterAmount(value) {
99-
if (value < 0) throw new Error("Negative water");
99+
if (value < 0) {
100+
value = 0;
101+
}
100102
this._waterAmount = value;
101103
}
102104

@@ -117,7 +119,7 @@ let coffeeMachine = new CoffeeMachine(100);
117119
coffeeMachine.waterAmount = -10; // Error: Negative water
118120
```
119121

120-
Now the access is under control, so setting the water below zero fails.
122+
Now the access is under control, so setting the water amount below zero becomes impossible.
121123

122124
## Read-only "power"
123125

@@ -159,7 +161,7 @@ class CoffeeMachine {
159161
_waterAmount = 0;
160162
161163
*!*setWaterAmount(value)*/!* {
162-
if (value < 0) throw new Error("Negative water");
164+
if (value < 0) value = 0;
163165
this._waterAmount = value;
164166
}
165167
@@ -199,12 +201,13 @@ class CoffeeMachine {
199201
*/!*
200202

201203
*!*
202-
#checkWater(value) {
203-
if (value < 0) throw new Error("Negative water");
204-
if (value > this.#waterLimit) throw new Error("Too much water");
204+
#fixWaterAmount(value) {
205+
if (value < 0) return 0;
206+
if (value > this.#waterLimit) return this.#waterLimit;
205207
}
206208
*/!*
207209

210+
<<<<<<< HEAD
208211
_waterAmount = 0;
209212

210213
set waterAmount(value) {
@@ -216,14 +219,23 @@ class CoffeeMachine {
216219

217220
get waterAmount() {
218221
return this.waterAmount;
222+
=======
223+
setWaterAmount(value) {
224+
this.#waterLimit = this.#fixWaterAmount(value);
225+
>>>>>>> c56e6a57ac3497aab77128c5bfca13513980709b
219226
}
220227

221228
}
222229

223230
let coffeeMachine = new CoffeeMachine();
224231

225232
*!*
233+
<<<<<<< HEAD
226234
coffeeMachine.#checkWater(); // Error
235+
=======
236+
// can't access privates from outside of the class
237+
coffeeMachine.#fixWaterAmount(123); // Error
238+
>>>>>>> c56e6a57ac3497aab77128c5bfca13513980709b
227239
coffeeMachine.#waterLimit = 1000; // Error
228240
*/!*
229241

@@ -246,7 +258,7 @@ class CoffeeMachine {
246258
}
247259

248260
set waterAmount(value) {
249-
if (value < 0) throw new Error("Negative water");
261+
if (value < 0) value = 0;
250262
this.#waterAmount = value;
251263
}
252264
}

1-js/11-async/05-promise-api/article.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ The first promise here was fastest, so it became the result. After the first set
269269

270270
## Promise.any
271271

272-
Similar to `Promise.race`, but waits only for the first fulfilled promise and gets its result. If all of the given promises are rejected, then the returned promise is rejected.
272+
Similar to `Promise.race`, but waits only for the first fulfilled promise and gets its result. If all of the given promises are rejected, then the returned promise is rejected with [`AggregateError`](mdn:js/AggregateError) - a special error object that stores all promise errors in its `errors` property.
273273

274274
The syntax is:
275275

@@ -289,6 +289,20 @@ Promise.any([
289289

290290
The first promise here was fastest, but it was rejected, so the second promise became the result. After the first fulfilled promise "wins the race", all further results are ignored.
291291

292+
Here's an example when all promises fail:
293+
294+
```js run
295+
Promise.any([
296+
new Promise((resolve, reject) => setTimeout(() => reject(new Error("Ouch!")), 1000)),
297+
new Promise((resolve, reject) => setTimeout(() => reject(new Error("Error!")), 2000))
298+
]).catch(error => {
299+
console.log(error.constructor.name); // AggregateError
300+
console.log(error.errors[0]); // Error: Ouch!
301+
console.log(error.errors[1]); // Error: Error
302+
});
303+
```
304+
305+
As you can see, error objects for failed promises are available in the `errors` property of the `AggregateError` object.
292306

293307
## Promise.resolve/reject
294308

@@ -352,7 +366,7 @@ There are 4 static methods of `Promise` class:
352366
- `status`: `"fulfilled"` or `"rejected"`
353367
- `value` (if fulfilled) or `reason` (if rejected).
354368
3. `Promise.race(promises)` -- waits for the first promise to settle, and its result/error becomes the outcome.
355-
4. `Promise.any(promises)` -- waits for the first promise to fulfill, and its result becomes the outcome. If all of the given promises rejects, it becomes the error of `Promise.any`.
369+
4. `Promise.any(promises)` -- waits for the first promise to fulfill, and its result becomes the outcome. If all of the given promises are rejected, [`AggregateError`](mdn:js/AggregateError) becomes the error of `Promise.any`.
356370
5. `Promise.resolve(value)` -- makes a resolved promise with the given value.
357371
6. `Promise.reject(error)` -- makes a rejected promise with the given error.
358372

1-js/99-js-misc/01-proxy/article.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,7 @@ Initially, `revoke` is separate from `proxy`, so that we can pass `proxy` around
969969

970970
We can also bind `revoke` method to proxy by setting `proxy.revoke = revoke`.
971971

972-
Another option is to create a `WeakMap` that has `proxy` as the key the corresponding `revoke` as the value, that allows to easily find `revoke` for a proxy:
972+
Another option is to create a `WeakMap` that has `proxy` as the key and the corresponding `revoke` as the value, that allows to easily find `revoke` for a proxy:
973973

974974
```js run
975975
*!*

2-ui/1-document/07-modifying-document/10-clock-setinterval/solution.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,19 @@ The clock-managing functions:
3939
```js
4040
let timerId;
4141

42-
function clockStart() { // run the clock
43-
timerId = setInterval(update, 1000);
42+
function clockStart() { // run the clock
43+
if (!timerId) { // only set a new interval if the clock is not running
44+
timerId = setInterval(update, 1000);
45+
}
4446
update(); // (*)
4547
}
4648

4749
function clockStop() {
4850
clearInterval(timerId);
49-
timerId = null;
51+
timerId = null; // (**)
5052
}
5153
```
5254

5355
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.
56+
57+
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()`.

0 commit comments

Comments
 (0)