Skip to content

Commit 0ef7054

Browse files
committed
works
1 parent b5438da commit 0ef7054

File tree

10 files changed

+211
-176
lines changed

10 files changed

+211
-176
lines changed

1-js/3-code-quality/20-coding-style/1-style-errors/solution.md renamed to 1-js/3-code-quality/2-coding-style/1-style-errors/solution.md

File renamed without changes.

1-js/3-code-quality/20-coding-style/1-style-errors/task.md renamed to 1-js/3-code-quality/2-coding-style/1-style-errors/task.md

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

1-js/3-code-quality/20-coding-style/figure-bracket-style.png renamed to 1-js/3-code-quality/2-coding-style/figure-bracket-style.png

File renamed without changes.

1-js/3-code-quality/20-coding-style/figure-bracket-style@2x.png renamed to 1-js/3-code-quality/2-coding-style/figure-bracket-style@2x.png

File renamed without changes.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
2+
# Polyfills
3+
4+
The JavaScript language steadily evolves. The new proposals get analyzed and, if they look 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).
5+
6+
Each JS engine has its own idea about what to implement first. It may implement proposals that are not approved yet and fail to implement things that are already in the spec, because they are less interesting or just harder to do.
7+
8+
So it's quite common for an engine to implement only the part of the standard.
9+
10+
A good page to see the current state of support for language features is <https://kangax.github.io/compat-table/es6/> (remember the link to use in the future when you know the language).
11+
12+
## Babel.JS
13+
14+
When we use all the modern features of the language, some engines may fail to support such code. Just as it was said, not all features are implemented everywhere.
15+
16+
Here Babel.JS comes to the rescue.
17+
18+
[Babel.JS](https://babeljs.io) is a [transpiler](https://en.wikipedia.org/wiki/Source-to-source_compiler). It rewrites the modern JavaScript code into the previous standard.
19+
20+
Actually, there are two parts in Babel:
21+
22+
1. The transpiler program, which rewrites the code.
23+
24+
The transpiler runs on a developer's computer. It rewrites the code, which is then bundled by a project build system (like [webpack](http://webpack.github.io/) or [brunch](http://brunch.io/)). Most build systems can support Babel easily.
25+
26+
2. The polyfill.
27+
28+
For some functions we also need add a special script that should run before our scripts and introduce modern functions that the engine may not support by itself. There's a term "polyfill" for such scripts.
29+
30+
The two interesting variants are [babel polyfill](https://babeljs.io/docs/usage/polyfill/) that supports a lot, but is big and the [polyfill.io](http://polyfill.io) service that allows to load/construct polyfills on-demand, depending on the features we need.
31+
32+
The transpiler and/or polyfill may be not needed if we orient towards more-or-less modern engines and don't use rarely supported features.
33+
34+
## Examples in the tutorial
35+
36+
```warn header="Browser support is required"
37+
Examples that use modern JS will work only if your browser supports it.
38+
```
39+
40+
````online
41+
Most examples are runnable at-place, like here:
42+
43+
```js run
44+
alert('Press the "Play" button in the upper-right corner to run');
45+
```
46+
47+
...But if it uses a feature that your browser does not support, an error is shown.
48+
49+
That doesn't mean that the example is wrong! It's just the browser lacking the support for certain features yet.
50+
````
51+
52+
[Chrome Canary](https://www.google.com/chrome/browser/canary.html) is good for more examples.
53+
54+
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.
55+
56+
Now we can go coding, so let's choose a good code editor.
57+

1-js/4-data-structures/2-number/article.md

Lines changed: 53 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ All numbers in JavaScript are stored in 64-bit format [IEEE-754](http://en.wikip
44

55
Let's recap what we know about them and add a little bit more.
66

7-
## Advanced ways to write
7+
## More ways to write a number
88

99
Imagine, we need to write a billion. The obvious way is:
1010

@@ -54,18 +54,19 @@ In other words, a negative number after `e` means a division by 1 with the given
5454
1.23e-6 = 1.23 / 1000000 (=0.00000123)
5555
```
5656

57-
## Hex, binary and octal numbers
57+
### Hex, binary and octal numbers
5858

59-
Hexadecimal numbers are widely used in JavaScript: to represent colors, encode characters and for many other things. So there exists a short way to write them: `0x` and then the number.
59+
[Hexadecimal](https://en.wikipedia.org/wiki/Hexadecimal) numbers are widely used in JavaScript: to represent colors, encode characters and for many other things. So there exists a short way to write them: `0x` and then the number.
6060

6161
For instance:
6262

6363
```js run
6464
alert( 0xff ); // 255
65-
alert( 0xFF ); // the same, letters can be uppercased, doesn't matter
65+
alert( 0xFF ); // 255 (the same, case doesn't matter)
6666
```
6767

68-
Binary and octal numeral systems are rarely used, but also possible to write them right way:
68+
Binary and octal numeral systems are rarely used, but also supported using `0b` and `0o` prefixes:
69+
6970

7071
```js run
7172
let a = 0b11111111; // binary form of 255
@@ -74,38 +75,36 @@ let b = 0o377; // octal form of 255
7475
alert( a == b ); // true, the same number 255 at both sides
7576
```
7677

77-
So as you can see, we prepend the number with `0x` for a hex, `0b` for a binary and `0o` for an octal.
78+
There are only 3 numeral systems with such support. For other numeral systems we should use function `parseInt` (goes later in this chapter).
7879

7980
## toString(base)
8081

81-
There is also a "reverse" method `num.toString(base)` that returns a string representation of `num` in the given `base`.
82+
There method `num.toString(base)` returns a string representation of `num` in the numeral system with the given `base`.
8283

8384
For example:
8485
```js run
8586
let num = 255;
8687

87-
alert( num.toString(2) ); // 11111111
88-
alert( num.toString(8) ); // 377
88+
alert( num.toString(16) ); // ff
89+
alert( num.toString(2) ); // 11111111
8990
```
9091

9192
The `base` can vary from `2` to `36`.
9293

9394
Most often use cases are:
9495

95-
- **16**, because hexadecimal numeral system is used for colors, character encodings etc, digits can be `0..9` or `A..F`.
96-
- **2** is mostly for debugging bitwise operations, digits can be only `0` or `1`.
97-
- **36** is the maximum, digits can be `0..9` or `A..Z`. The whole latin alphabet is used to represent a number.
98-
99-
A funny, but useful case for `36` is when we need to turn a long numeric identifier into something shorter, for example to make a short url. The base-36 notation is an easy way to go:
96+
- **base=16** is used for colors, character encodings etc, digits can be `0..9` or `A..F`.
97+
- **base=2** is mostly for debugging bitwise operations, digits can be `0` or `1`.
98+
- **base=36** is the maximum, digits can be `0..9` or `A..Z`. The whole latin alphabet is used to represent a number. A funny, but useful case for `36` is when we need to turn a long numeric identifier into something shorter, for example to make a short url. Can simply represent it in the numeral system with base `36`:
10099

101-
```js run
102-
alert( 123456..toString(36) ); // 2n9c
103-
```
100+
```js run
101+
alert( 123456..toString(36) ); // 2n9c
102+
```
104103

105104
```warn header="Two dots to call a method"
106-
If we want to call a method directly on a number, like `toString` in the example above, then we need to place two dots `..` after it.
105+
Please note that two dots in `123456..toString(36)` is not a typo. If we want to call a method directly on a number, like `toString` in the example above, then we need to place two dots `..` after it.
107106
108-
If we place a single dot: `123456.toString(36)`, then there will be an error, because JavaScript awaits the decimal part after the dot. And if we place one more dot, then JavaScript knows that the number has finished and we mean the method.
107+
If we placed a single dot: `123456.toString(36)`, then there would be an error, because JavaScript syntax implies the decimal part after the first dot. And if we place one more dot, then JavaScript knows that the decimal part is empty and now goes the method.
109108
```
110109

111110
## Rounding
@@ -126,22 +125,17 @@ There are following built-in functions for rounding:
126125
`Math.trunc` (not supported by Internet Explorer)
127126
: Removes the decimal part: `3.1` becomes `3`, `-1.1` becomes `-1`.
128127

128+
Here's the table to summarize the differences between them:
129129
130-
Looks simple, right? Indeed it is.
131-
132-
Here's the table to make edge cases more obvious:
133-
134-
| | `floor` | `ceil` | `round` | `trunc` |
130+
| | `Math.floor` | `Math.ceil` | `Math.round` | `Math.trunc` |
135131
|---|---------|--------|---------|---------|
136132
|`3.1`| `3` | `4` | `3` | `3` |
137133
|`3.6`| `3` | `4` | `4` | `3` |
138134
|`-1.1`| `-2` | `-1` | `-1` | `-1` |
139135
|`-1.6`| `-2` | `-1` | `-2` | `-1` |
140136
141137
142-
These functions cover all possible ways to deal with the decimal part.
143-
144-
But what if we'd like to round the number to `n-th` digit after the point?
138+
These functions cover all possible ways to deal with the decimal part as a whole. But what if we'd like to round the number to `n-th` digit after the point?
145139

146140
For instance, we have `1.2345` and want to round it to 2 digits, getting only `1.23`.
147141

@@ -170,77 +164,66 @@ There are two ways to do so.
170164
alert( num.toFixed(1) ); // "12.4"
171165
```
172166

173-
The resulting string is zero-padded to the required precision if needed:
167+
Please note that result of `toFixed` is a string. If the decimal part is shorter than required, zeroes are appended to its end:
174168

175169
```js run
176170
let num = 12.34;
177171
alert( num.toFixed(5) ); // "12.34000", added zeroes to make exactly 5 digits
178172
```
179173

180-
Let's note once again that the result is a string. We can convert it to a number using the unary plus or a `Number()` call.
174+
We can convert it to a number using the unary plus or a `Number()` call: `+num.toFixed(5)`.
181175

182176
## Imprecise calculations
183177

184-
Internally, each number occupies 64 bits, 52 of them are used to store the digits, 11 of them store the location of the point (to allow fractions) and 1 is the sign.
178+
Internally, a number is represented in 64-bit format [IEEE-754](http://en.wikipedia.org/wiki/IEEE_754-1985). So, there are exactly 64 bits to store a number: 52 of them are used to store the digits, 11 of them store the position of the decimal point (they are zero for integer numbers) and 1 bit for the sign.
185179

186-
If a number is too big, it would overflow the storage, potentially giving an infinity:
180+
If a number is too big, it would overflow the 64-bit storage, potentially giving an infinity:
187181

188182
```js run
189183
alert( 1e500 ); // Infinity
190184
```
191185

192-
But what happens much more often is the loss of precision.
186+
But what may be a little bit more obvious, but happens much often is the loss of precision.
193187

194-
Consider this:
188+
Consider this (falsy!) test:
195189

196190
```js run
197191
alert( 0.1 + 0.2 == 0.3 ); // *!*false*/!*
198192
```
199193

200-
Yes, you got that right, the sum of `0.1` and `0.2` is not `0.3`. What is it then?
194+
Yes, indeed, if we check whether the sum of `0.1` and `0.2` is `0.3`, we get `false`.
195+
196+
Strange! What is it then if not `0.3`?
201197

202198
```js run
203199
alert( 0.1 + 0.2 ); // 0.30000000000000004
204200
```
205201

206-
Imagine you're making an e-shopping site and the visitor puts `$0.10` and `$0.20` goods into his chart. The order total will be `$0.30000000000000004`. That would surprise anyone.
202+
Ouch! There are more consequences than an incorrect comparison here. Imagine you're making an e-shopping site and the visitor puts `$0.10` and `$0.20` goods into his chart. The order total will be `$0.30000000000000004`. That would surprise anyone.
207203

208204
Why does it work like that?
209205

210-
A number is stored in memory in it's binary form, as a sequence of ones and zeroes. But decimal fractions like `0.1`, `0.2` are actually unending fractions in their binary form.
206+
A number is stored in memory in it's binary form, as a sequence of ones and zeroes. But fractions like `0.1`, `0.2` that look simple in the decimal numeric system are actually unending fractions in their binary form.
211207

212-
In other words, what is `0.1`? It is one divided by ten.
208+
In other words, what is `0.1`? It is one divided by ten `1/10`, one-tenth. In decimal numeral system such numbers are easily representable. Compare it to one-third: `1/3`. It becomes an endless fraction `0.33333(3)`.
213209

214-
But in the binary numeral system, we can only get "clean" division by the powers of two:
210+
So, division by powers `10` is guaranteed to look well in the decimal system, but the division by `3` is not. For the same reason, in the binary numeral system, the division by powers of `2` is guaranteed to look good, but `1/10` becomes an endless binary fraction.
215211

216-
```js
217-
// binary numbers
218-
10 = 1 * 2
219-
100 = 1 * 4
220-
1000 = 1 * 8
221-
...
222-
// now the reverse
223-
0.1 = 1 / 2
224-
0.01 = 1 / 4
225-
0.001 = 1 / 8
226-
...
227-
```
212+
There's just no way to store *exactly 0.1* or *exactly 0.2* in the binary system, just like there is no way to store one-third as a decimal fraction.
228213

229-
So, there's just no way to store *exactly 0.1* or *exactly 0.2* as a binary fraction. Just like there is no way to store one-third as a decimal fraction.
230-
231-
The numeric format "fixes" that by storing the nearest possible number. There are rounding rules that normally don't allow us to see that "tiny precision loss", but it still exists.
214+
The numeric format IEEE-754 solves that by storing the nearest possible number. There are rounding rules that normally don't allow us to see that "tiny precision loss", so the number shows up as `0.3`. But the loss still exists.
232215

233216
We can see it like this:
234217
```js run
235218
alert( 0.1.toFixed(20) ); // 0.10000000000000000555
236219
```
237220

238-
And when we sum two numbers, then their "precision losses" sum up too.
221+
And when we sum two numbers, then their "precision losses" sum up.
239222

240223
That's why `0.1 + 0.2` is not exactly `0.3`.
241224

242225
```smart header="Not only JavaScript"
243-
The same problem exists in many other programming languages.
226+
The same issue exists in many other programming languages.
244227

245228
PHP, Java, C, Perl, Ruby give exactly the same result, because they are based on the same numeric format.
246229
```
@@ -267,14 +250,15 @@ Can we work around the problem? Sure, there's a number of ways:
267250
alert( (0.1*10 + 0.2*10) / 10 ); // 0.3
268251
```
269252

270-
It works, because `0.1*10 = 1` and `0.2 * 10 = 2` are integers. The rounding rules of the format fix the precision loss in the process of multiplication. Now the resulting integer numbers can now be exactly represented in the binary format.
253+
It works, because when we get `0.1*10 = 1` and `0.2 * 10 = 2` then both numbers are integers, there's no precision loss for them.
271254

272255
3. If it's a shop, then the most radical solution would be to store all prices in cents. No fractions at all. But what if we apply a discount of 30%? In practice, totally evading fractions is rarely feasible, so the solutions listed above are here to help.
273256

274257
````smart header="The funny thing"
275-
Hello! I'm a self-increasing number!
258+
Try running this:
276259

277260
```js run
261+
// Hello! I'm a self-increasing number!
278262
alert( 9999999999999999 ); // shows 10000000000000000
279263
```
280264

@@ -283,31 +267,24 @@ The reason is the same: loss of precision. There are 64 bits for the number, 52
283267
JavaScript doesn't trigger an error in such case. It does the best to fit the number into the format. Unfortunately, the format is not big enough.
284268
````
285269

286-
## parseInt and parseFloat
287-
288-
We already know the easiest way to convert a value into a number. It's the unary plus!
289-
290-
But in web-programming we sometimes meet values that
291-
292-
293270
## Tests: isFinite and isNaN
294271

295-
Remember those two special numeric values?
272+
Remember the two special numeric values?
296273

297274
- `Infinite` (and `-Infinite`) is a special numeric value that is greater (less) than anything.
298275
- `NaN` represends an error.
299276

300-
There are special functions to check for them:
277+
They belong to the type `number`, but are not "normal" numbers, so there are special functions to check for them:
301278

302279

303-
- `isNaN(value)` converts its argument to a number and then tests if for being `NaN:
280+
- `isNaN(value)` converts its argument to a number and then tests if for being `NaN`:
304281

305282
```js run
306283
alert( isNaN(NaN) ); // true
307284
alert( isNaN("str") ); // true
308285
```
309286

310-
But can't we just use `===` here? Funny, but no. The value `NaN` is unique. It does not equal anything including itself:
287+
But do we need the function? Can we just use the comparison `=== NaN`? Funny, but no. The value `NaN` is unique in that it does not equal anything including itself:
311288

312289
```js run
313290
alert( NaN === NaN ); // false
@@ -327,15 +304,15 @@ Sometimes `isFinite` is used to validate the string value for being a regular nu
327304
```js run
328305
let num = +prompt("Enter a number", '');
329306

330-
// isFinite will be true only for regular numbers
331-
alert(`num:${num}, isFinite:${isFinite(num)}`);
307+
// will be true unless you enter Infinity, -Infinity or not a number
308+
alert( isFinite(num) );
332309
```
333310

334-
Please note that an empty or a space-only string is treated as `0` in the described case. If it's not what's needed, then additional checks are required.
311+
Please note that an empty or a space-only string is treated as `0` in all numeric functions. If it's not what's needed, then additional checks are required.
335312

336313
## parseInt and parseFloat
337314

338-
Regular numeric conversion is harsh. If a value is not exactly a number, it fails:
315+
The numeric conversion using a plus `+` or `Number()` is strict. If a value is not exactly a number, it fails:
339316

340317
```js run
341318
alert( +"100px" ); // NaN
@@ -404,8 +381,7 @@ A few examples:
404381
alert( Math.pow(2, 10) ); // 2 in power 10 = 1024
405382
```
406383

407-
408-
You can find the full list of functions in the docs for the [Math](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math) object.
384+
There are more functions and constants in `Math`, including trigonometry, you can find them in the [docs for the Math](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math) object.
409385

410386
## Summary
411387

@@ -427,10 +403,10 @@ For converting values like `12pt` and `100px` to a number:
427403
For fractions:
428404

429405
- Round using `Math.floor`, `Math.ceil`, `Math.trunc`, `Math.round` or `num.toFixed(precision)`.
430-
- Remember about the loss of precision when comparing or doing maths.
406+
- Remember about the loss of precision when working with fractions.
431407

432-
Mathematical functions:
408+
More mathematical functions:
433409

434-
- See the [Math](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math) manual when you need them. The library is very small, but can cover basic needs.
410+
- See the [Math](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math) object when you need them. The library is very small, but can cover basic needs.
435411

436412

0 commit comments

Comments
 (0)