This commit is contained in:
Ilya Kantor 2019-07-08 14:08:07 +03:00
parent 5e9eca374f
commit f30e0d4722
4 changed files with 38 additions and 28 deletions

View file

@ -3,16 +3,15 @@
This book is a *tutorial*. It aims to help you gradually learn the language. But once you're familiar with the basics, you'll need other sources. This book is a *tutorial*. It aims to help you gradually learn the language. But once you're familiar with the basics, you'll need other sources.
## Specification ## Specification
**The ECMA-262 specification** contains the most in-depth, detailed and formalized information about JavaScript. It defines the language. **The ECMA-262 specification** contains the most in-depth, detailed and formalized information about JavaScript. It defines the language.
But being that formalized, it's difficult to understand at first. So if you need the most trustworthy source of information about the language details, it's the right place. But it's not for everyday use. But being that formalized, it's difficult to understand at first. So if you need the most trustworthy source of information about the language details, the specification is the right place. But it's not for everyday use.
The latest draft is at <https://tc39.es/ecma262/>. The latest draft is at <https://tc39.es/ecma262/>.
To read about bleeding-edge features, that are not yet widely supported, see proposals at <https://github.com/tc39/proposals>. To read about new bleeding-edge features, that are "almost standard", see proposals at <https://github.com/tc39/proposals>.
Also, if you're in developing for the browser, then there are other specs covered in the [second part](info:browser-environment) of the tutorial. Also, if you're in developing for the browser, then there are other specs covered in the [second part](info:browser-environment) of the tutorial.

View file

@ -17,7 +17,7 @@ let double = "double-quoted";
let backticks = `backticks`; let backticks = `backticks`;
``` ```
Single and double quotes are essentially the same. Backticks, however, allow us to embed any expression into the string, including function calls: Single and double quotes are essentially the same. Backticks, however, allow us to embed any expression into the string, by wrapping it in `${…}`:
```js run ```js run
function sum(a, b) { function sum(a, b) {
@ -39,7 +39,11 @@ let guestList = `Guests:
alert(guestList); // a list of guests, multiple lines alert(guestList); // a list of guests, multiple lines
``` ```
If we try to use single or double quotes in the same way, there will be an error: Looks natural, right? But single or double quotes do not work this way.
If we use them and try to use multiple lines, there'll be an error:
```js run ```js run
let guestList = "Guests: // Error: Unexpected token ILLEGAL let guestList = "Guests: // Error: Unexpected token ILLEGAL
* John"; * John";
@ -60,27 +64,33 @@ let guestList = "Guests:\n * John\n * Pete\n * Mary";
alert(guestList); // a multiline list of guests alert(guestList); // a multiline list of guests
``` ```
For example, these two lines describe the same: For example, these two lines are equal, just written differently:
```js run ```js run
alert( "Hello\nWorld" ); // two lines using a "newline symbol" let str1 = "Hello\nWorld"; // two lines using a "newline symbol"
// two lines using a normal newline and backticks // two lines using a normal newline and backticks
alert( `Hello let str2 = `Hello
World` ); World`;
alert(str1 == str2); // true
``` ```
There are other, less common "special" characters as well. Here's the list: There are other, less common "special" characters.
Here's the full list:
| Character | Description | | Character | Description |
|-----------|-------------| |-----------|-------------|
|`\b`|Backspace|
|`\f`|Form feed|
|`\n`|New line| |`\n`|New line|
|`\r`|Carriage return| |`\r`|Carriage return: not used alone. Windows text files use a combination of two characters `\n\r` to represent a line break. |
|`\'`, `\"`|Quotes|
|`\\`|Backslash|
|`\t`|Tab| |`\t`|Tab|
|`\uNNNN`|A unicode symbol with the hex code `NNNN`, for instance `\u00A9` -- is a unicode for the copyright symbol `©`. It must be exactly 4 hex digits. | |`\b`, `\f`,`\v` | Backspace, Form Feed, Vertical Tab -- kept for compatibility, not used nowadays. |
|`\u{NNNNNNNN}`|Some rare characters are encoded with two unicode symbols, taking up to 4 bytes. This long unicode requires braces around it.| |`\xXX`|Unicode character with the given hexadimal unicode `XX`, e.g. `'\x7A'` is the same as `'z'`.|
|`\uXXXX`|A unicode symbol with the hex code `XXXX` in UTF-16 encoding, for instance `\u00A9` -- is a unicode for the copyright symbol `©`. It must be exactly 4 hex digits. |
|`\u{X…XXXXXX}` (1 to 6 hex characters)|A unicode symbol with the given UTF-32 encoding. Some rare characters are encoded with two unicode symbols, taking up to 4 bytes. This way we can insert long codes. |
Examples with unicode: Examples with unicode:
@ -102,7 +112,7 @@ alert( 'I*!*\'*/!*m the Walrus!' ); // *!*I'm*/!* the Walrus!
As you can see, we have to prepend the inner quote by the backslash `\'`, because otherwise it would indicate the string end. As you can see, we have to prepend the inner quote by the backslash `\'`, because otherwise it would indicate the string end.
Of course, that refers only to the quotes that are the same as the enclosing ones. So, as a more elegant solution, we could switch to double quotes or backticks instead: Of course, only to the quotes that are the same as the enclosing ones need to be escaped. So, as a more elegant solution, we could switch to double quotes or backticks instead:
```js run ```js run
alert( `I'm the Walrus!` ); // I'm the Walrus! alert( `I'm the Walrus!` ); // I'm the Walrus!
@ -455,7 +465,7 @@ Let's recap these methods to avoid any confusion:
```smart header="Which one to choose?" ```smart header="Which one to choose?"
All of them can do the job. Formally, `substr` has a minor drawback: it is described not in the core JavaScript specification, but in Annex B, which covers browser-only features that exist mainly for historical reasons. So, non-browser environments may fail to support it. But in practice it works everywhere. All of them can do the job. Formally, `substr` has a minor drawback: it is described not in the core JavaScript specification, but in Annex B, which covers browser-only features that exist mainly for historical reasons. So, non-browser environments may fail to support it. But in practice it works everywhere.
The author finds themself using `slice` almost all the time. Of the other two variants, `slice` is a little bit more flexible, it allows negative arguments and shorter to write. So, it's enough to remember solely `slice` of these three methods.
``` ```
## Comparing strings ## Comparing strings
@ -530,7 +540,7 @@ The characters are compared by their numeric code. The greater code means that t
### Correct comparisons ### Correct comparisons
The "right" algorithm to do string comparisons is more complex than it may seem, because alphabets are different for different languages. The same-looking letter may be located differently in different alphabets. The "right" algorithm to do string comparisons is more complex than it may seem, because alphabets are different for different languages.
So, the browser needs to know the language to compare. So, the browser needs to know the language to compare.
@ -550,7 +560,7 @@ For instance:
alert( 'Österreich'.localeCompare('Zealand') ); // -1 alert( 'Österreich'.localeCompare('Zealand') ); // -1
``` ```
This method actually has two additional arguments specified in [the documentation](mdn:js/String/localeCompare), which allows it to specify the language (by default taken from the environment) and setup additional rules like case sensitivity or should `"a"` and `"á"` be treated as the same etc. This method actually has two additional arguments specified in [the documentation](mdn:js/String/localeCompare), which allows it to specify the language (by default taken from the environment, letter order depends on the language) and setup additional rules like case sensitivity or should `"a"` and `"á"` be treated as the same etc.
## Internals, Unicode ## Internals, Unicode
@ -580,7 +590,7 @@ We actually have a single symbol in each of the strings above, but the `length`
`String.fromCodePoint` and `str.codePointAt` are few rare methods that deal with surrogate pairs right. They recently appeared in the language. Before them, there were only [String.fromCharCode](mdn:js/String/fromCharCode) and [str.charCodeAt](mdn:js/String/charCodeAt). These methods are actually the same as `fromCodePoint/codePointAt`, but don't work with surrogate pairs. `String.fromCodePoint` and `str.codePointAt` are few rare methods that deal with surrogate pairs right. They recently appeared in the language. Before them, there were only [String.fromCharCode](mdn:js/String/fromCharCode) and [str.charCodeAt](mdn:js/String/charCodeAt). These methods are actually the same as `fromCodePoint/codePointAt`, but don't work with surrogate pairs.
But, for instance, getting a symbol can be tricky, because surrogate pairs are treated as two characters: Getting a symbol can be tricky, because surrogate pairs are treated as two characters:
```js run ```js run
alert( '𝒳'[0] ); // strange symbols... alert( '𝒳'[0] ); // strange symbols...
@ -608,7 +618,7 @@ In many languages there are symbols that are composed of the base character with
For instance, the letter `a` can be the base character for: `àáâäãåā`. Most common "composite" character have their own code in the UTF-16 table. But not all of them, because there are too many possible combinations. For instance, the letter `a` can be the base character for: `àáâäãåā`. Most common "composite" character have their own code in the UTF-16 table. But not all of them, because there are too many possible combinations.
To support arbitrary compositions, UTF-16 allows us to use several unicode characters. The base character and one or many "mark" characters that "decorate" it. To support arbitrary compositions, UTF-16 allows us to use several unicode characters: the base character followed by one or many "mark" characters that "decorate" it.
For instance, if we have `S` followed by the special "dot above" character (code `\u0307`), it is shown as Ṡ. For instance, if we have `S` followed by the special "dot above" character (code `\u0307`), it is shown as Ṡ.
@ -634,7 +644,7 @@ For instance:
alert( 'S\u0307\u0323' ); // Ṩ, S + dot above + dot below alert( 'S\u0307\u0323' ); // Ṩ, S + dot above + dot below
alert( 'S\u0323\u0307' ); // Ṩ, S + dot below + dot above alert( 'S\u0323\u0307' ); // Ṩ, S + dot below + dot above
alert( 'S\u0307\u0323' == 'S\u0323\u0307' ); // false alert( 'S\u0307\u0323' == 'S\u0323\u0307' ); // false, different characters (?!)
``` ```
To solve this, there exists a "unicode normalization" algorithm that brings each string to the single "normal" form. To solve this, there exists a "unicode normalization" algorithm that brings each string to the single "normal" form.
@ -660,7 +670,7 @@ If you want to learn more about normalization rules and variants -- they are des
## Summary ## Summary
- There are 3 types of quotes. Backticks allow a string to span multiple lines and embed expressions. - There are 3 types of quotes. Backticks allow a string to span multiple lines and embed expressions `${…}`.
- Strings in JavaScript are encoded using UTF-16. - Strings in JavaScript are encoded using UTF-16.
- We can use special characters like `\n` and insert letters by their unicode using `\u...`. - We can use special characters like `\n` and insert letters by their unicode using `\u...`.
- To get a character, use: `[]`. - To get a character, use: `[]`.
@ -673,6 +683,6 @@ There are several other helpful methods in strings:
- `str.trim()` -- removes ("trims") spaces from the beginning and end of the string. - `str.trim()` -- removes ("trims") spaces from the beginning and end of the string.
- `str.repeat(n)` -- repeats the string `n` times. - `str.repeat(n)` -- repeats the string `n` times.
- ...and more. See the [manual](mdn:js/String) for details. - ...and more to be found in the [manual](mdn:js/String).
Strings also have methods for doing search/replace with regular expressions. But that topic deserves a separate chapter, so we'll return to that later. Strings also have methods for doing search/replace with regular expressions. But that's big topic, so it's explained in a separate tutorial section <info:regular-expressions>.

View file

@ -32,14 +32,15 @@ function onUpload(req, res) {
let fileStream; let fileStream;
// for byte 0, create a new file, otherwise check the size and append to existing one // if startByte is 0 or not set, create a new file, otherwise check the size and append to existing one
if (startByte == 0) { if (!startByte) {
upload.bytesReceived = 0; upload.bytesReceived = 0;
fileStream = fs.createWriteStream(filePath, { fileStream = fs.createWriteStream(filePath, {
flags: 'w' flags: 'w'
}); });
debug("New file created: " + filePath); debug("New file created: " + filePath);
} else { } else {
// we can check on-disk file size as well to be sure
if (upload.bytesReceived != startByte) { if (upload.bytesReceived != startByte) {
res.writeHead(400, "Wrong start byte"); res.writeHead(400, "Wrong start byte");
res.end(upload.bytesReceived); res.end(upload.bytesReceived);

View file

@ -5,7 +5,7 @@ class Uploader {
this.onProgress = onProgress; this.onProgress = onProgress;
// create fileId that uniquely identifies the file // create fileId that uniquely identifies the file
// we can also add user session identifier, to make it even more unique // we could also add user session identifier (if had one), to make it even more unique
this.fileId = file.name + '-' + file.size + '-' + +file.lastModifiedDate; this.fileId = file.name + '-' + file.size + '-' + +file.lastModifiedDate;
} }