This commit is contained in:
Ilya Kantor 2020-11-21 20:38:22 +03:00
parent db4a880974
commit 06cdd5b84a
23 changed files with 110 additions and 775 deletions

View file

@ -1,251 +1,14 @@
# Basic concepts
# Code structure
Let's take a piece of JavaScript code and discuss it line by line.
Please don't hesitate to open "read more" sections below. They aren't strictly required, but contain valueable information.
```js run
"use strict";
let message = "Hello!";
alert(message);
```
Click the "run" icon ▷ in the right-upper corner to see how it works.
Now we'll go over it line by line.
## Strict mode
The first line:
```js
"use strict";
```
The code starts with the special directive: `"use strict"`.
To understand what it means, let's make a short dive into the history of JavaScript.
JavaScript appeared many years ago, in 1995. For a long time, it evolved without compatibility issues. New features were added to the language while old functionality didn't change.
That had the benefit of never breaking existing code. But the downside was that any mistake or an imperfect decision made by JavaScript's creators got stuck in the language forever.
This was the case until 2009, when the 5th version of the standard appeared. It added new features to the language and modified some of the existing ones.
Now the important part.
**To keep the old code working, these modernizations are off by default.** We need to explicitly enable them with a special directive: `"use strict"`
With that directive on top the script runs in so-called "strict mode". Or, we'd better say "modern mode", because that's what it essentially is.
![](use-strict.svg)
Some JavaScript features enable strict mode automatically, e.g. classes and modules, so that we don't need to write `"use strict"` for them. We'll cover these features later.
**Here, in the tutorial, we'll always use strict mode, unless explicitly stated otherwise.**
We're studying modern JavaScript after all. But you'll also see notes about how things work without `use strict`, just in case you come across an old script.
## Variables
A [variable](https://en.wikipedia.org/wiki/Variable_(computer_science)) is a "named storage" for data. We can use variables to store goodies, visitors, and so on.
The second line declares (creates) a variable with the name `message` and stores the string `"John"` in it:
```js
let message = "Hello!";
```
We could also split this line into two:
```js
let message;
message = "Hello!";
```
Here, we first declare the variable with `let message`, and then assign the value.
We can easily grasp the concept of a "variable" if we imagine it as a "box" for data, with a uniquely-named sticker on it.
For instance, the variable `message` can be imagined as a box labeled `"message"` with the value `"Hello!"` in it:
![](variable.svg)
We can put any value in the box.
We can also change it as many times as we want:
```js
let message;
message = "Hello!";
message = "World!"; // value changed
```
When the value is changed, the old data is removed from the variable:
![](variable-change.svg)
We can also declare multiple variables and copy data from one into another.
```js run
let hello = "Hello!";
let message;
*!*
// copy the value "Hello!" from hello into message
message = hello;
*/!*
```
Now we have two variables, both store the same string:
![](variable-copy-value.svg)
````warn header="Re-declaration triggers an error"
A variable can be declared only once.
A repeated declaration of the same variable is an error:
```js run
let message = "One";
// repeated 'let' leads to an error
let message = "Two"; // SyntaxError: 'message' has already been declared
```
So, we should declare a variable once and then refer to it without `let`.
````
````warn header="Omitting `let` is possible without `use strict`"
In the old times, it was possible to create a variable by a mere assignment of the value without using `let`. This still works now if the script runs in the "compatibility mode", without `use strict`:
```js run no-strict
// note: no "use strict" in this example
num = 5; // the variable "num" is created if it didn't exist
alert(num); // 5
```
This is a bad practice and would cause an error in strict mode.
````
### Variable naming
There are two limitations on variable names in JavaScript:
1. The name must contain only letters, digits, or the symbols `$` and `_`.
2. The first character must not be a digit.
Examples of valid names:
```js
let userName;
let test123;
```
When the name contains multiple words, [camelCase](https://en.wikipedia.org/wiki/CamelCase) is commonly used. That is: words go one after another, each word after the first one starts with a capital letter: `myVeryLongName`.
Examples of incorrect variable names:
```js no-beautify
let 1a; // cannot start with a digit
let my-name; // hyphens '-' aren't allowed in the name
```
```smart header="Case matters"
Variables named `apple` and `AppLE` are two different variables.
```
````smart header="Non-Latin letters are allowed, but not recommended"
It is possible to use any language, including cyrillic letters or even hieroglyphs, like this:
```js
let имя = "...";
let 我 = "...";
```
Technically, there is no error here. Such names are allowed, but there is an international convention to use English in variable names. Even if you're writing a small script, it may have a long life ahead. People from other countries may need to read it in the future.
````
````warn header="Reserved names"
There is a [list of reserved words](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Keywords), which cannot be used as variable names because they are used by the language itself.
For example: `let`, `class`, `return`, and `function` are reserved.
The code below gives a syntax error:
```js run no-beautify
let let = 5; // can't name a variable "let", error!
let return = 5; // also can't name it "return", error!
```
````
### Other ways to declare a variable
Besides `let`, there are two other keywords that declare a variable:
- `var` (e.g. `var message`) -- the outdated way to declare a variable, you can meet it in really old scripts.
Please don't use it.
- `const` (e.g. `const message`) -- declares a *constant* variable.
A constant variable must be declared with the initial value, and afterwards it can't be reassigned.
For example:
```js run
const birthday = "18.04.1982";
birthday = "01.01.1970"; // Error: Assignment to constant variable.
```
A person might change their name, but not the birthday. The idea of `const` is to let everyone (including the JavaScript engine)¸know about it.
## Statements and semicolons
The third line of our code is:
```js
alert(message);
```
<hr>
It means that the script should run in the "strict mode".
Historically,
If we omit it, then some language features will work a little bit differently. We'll mention the differences later as
or, in other words, in the modern mode of execution.
There are basically two modes of script execution of a script:
- The "strict mode", .
- The "strict mode".
What does it mean?
Well,
There was a time long ago when JavaScript was a bit different language.
The core elements of scripts are statements.
## Statements
Statements are syntax constructs and commands that perform actions, make JavaScript "do" something.
Here's an example of a statement:
```js run
alert('Hello, world!');
alert("Hello, world!");
```
Click the "run" icon ▷ in the right-upper corner to see how it works.
@ -257,32 +20,30 @@ Statements can be separated with a semicolon.
For example, here we split "Hello World" into two alerts:
```js run no-beautify
alert('Hello'); alert('World');
alert("Hello"); alert("World");
```
Usually, statements are written on separate lines to make the code more readable:
```js run no-beautify
alert('Hello');
alert('World');
alert("Hello");
alert("World");
```
## Semicolons..or not?
A semicolon may be omitted in most cases when a line break exists.
This would also work:
```js run no-beautify
alert('Hello')
alert('World')
alert("Hello")
alert("World")
```
Here, JavaScript interprets the line break as an "implicit" semicolon. This is called an [automatic semicolon insertion](https://tc39.github.io/ecma262/#sec-automatic-semicolon-insertion).
Usually, JavaScript interprets the line break as an "implicit" semicolon. This is called an [automatic semicolon insertion](https://tc39.github.io/ecma262/#sec-automatic-semicolon-insertion).
**In most cases, a newline implies a semicolon. But "in most cases" does not mean "always"!**
There are cases when a newline does not mean a semicolon.
For example:
But there are exceptions, like this:
```js run no-beautify
alert(1 +
@ -291,11 +52,9 @@ alert(1 +
The code outputs `3` because JavaScript does not insert semicolons after the plus `+`. It is intuitively obvious that if the line ends with a plus `"+"`, then it is an incomplete expression, that's continued on the next line. And in this case that works as intended.
**But there are situations where JavaScript "fails" to assume a semicolon where it is really needed.**
**But there are situations where our intuition differs from JavaScript auto-insertion rules.**
**TODO: The section below is optional, so it's collapsed by default - make it a hint on first open?**
**TODO: design this.**
That may lead to subtle errors.
````spoiler header="Read more about it"
@ -305,14 +64,14 @@ If you're curious to see a concrete example of such an error, check this code ou
[1, 2].forEach(alert)
```
If the code is too complex to understand, that's all right. You don't have to.
The code may be too advanced to understand right now, but that's all right.
All you need now is to run the code and remember the result: it shows `1` then `2`.
All you need to do is to run the code and remember the result: it shows `1` then `2`.
Let's add an `alert` before the code and *not* finish it with a semicolon:
```js run no-beautify
alert("Without a semicolon after me - error")
alert("Without a semicolon after the alert - error")
[1, 2].forEach(alert)
```
@ -326,7 +85,7 @@ alert("With a semicolon after me - all ok");
[1, 2].forEach(alert)
```
The error in the no-semicolon variant occurs because JavaScript doesn't "auto-insert" a semicolon on a newline before square brackets `[...]`.
The error in the no-semicolon variant occurs because JavaScript doesn't "auto-insert" a semicolon if a newline is followed by squares brackets `[...]`.
So, because the semicolon is not auto-inserted, the code in the first example is treated as a single statement. Here's how the engine sees it:
@ -337,9 +96,9 @@ alert("There will be an error")[1, 2].forEach(alert)
But such a merge in this case is just wrong, hence the error. This can happen in other situations as well.
````
To prevent such errors, we recommend putting semicolons between statements even if they are separated by newlines. This rule is widely adopted by the community.
We recommend putting semicolons between statements even if they are separated by newlines. This rule is widely adopted by the community. Let's note once again -- *it is possible* to leave out semicolons most of the time. But it's safer --
especially for a beginner -- to use them.
Let's note once again -- *it is possible* to leave out semicolons most of the time. But it's safer -- especially for a beginner -- to use them.
## Comments
@ -354,9 +113,9 @@ The rest of the line is a comment. It may occupy a full line of its own or follo
Like here:
```js run
// This comment occupies a line of its own
alert('Hello');
alert("Hello");
alert('World'); // This comment follows the statement
alert("World"); // This comment follows the statement
```
**Multiline comments start with a forward slash and an asterisk <code>/&#42;</code> and end with an asterisk and a forward slash <code>&#42;/</code>.**
@ -367,8 +126,8 @@ Like this:
/* An example with two messages.
This is a multiline comment.
*/
alert('Hello');
alert('World');
alert("Hello");
alert("World");
```
The content of comments is ignored, so if we put code inside <code>/&#42; ... &#42;/</code>, it won't execute.
@ -377,9 +136,9 @@ Sometimes it can be handy to temporarily disable a part of code:
```js run
/* Commenting out the code
alert('Hello');
alert("Hello");
*/
alert('World');
alert("World");
```
```smart header="Use hotkeys!"
@ -395,7 +154,7 @@ Such code will die with an error:
/*
/* nested comment ?!? */
*/
alert( 'World' );
alert( "World" );
```
````
@ -403,4 +162,26 @@ Please, don't hesitate to comment your code.
Comments increase the overall code footprint, but that's not a problem at all. There are many tools which minify code before publishing to a production server. They remove comments, so they don't appear in the working scripts. Therefore, comments do not have negative effects on production at all.
Later in the tutorial there will be a chapter <info:code-quality> that also explains how to write better comments.
## Strict mode
JavaScript appeared many years ago, in 1995. Then ,for a long time, it evolved without compatibility issues. New features were added to the language while old functionality didn't change.
That had the benefit of never breaking existing code. But the downside was that any mistake or an imperfect decision made by JavaScript's creators got stuck in the language forever.
This was the case until 2009, when the 5th version of the standard appeared. It added new features to the language and modified some of the existing ones.
Now the important part.
**To keep the old code working, these newer modifications are off by default.**
We need to explicitly enable them with a special directive: `"use strict"`
With that directive on top the script runs in so-called "strict mode". Or, we'd better say "modern mode", because that's what it essentially is.
![](use-strict.svg)
Some JavaScript features enable strict mode automatically, e.g. classes and modules, so that we don't need to write `"use strict"` for them. We'll cover these features later.
**Here, in the tutorial, we'll always use strict mode, unless explicitly stated otherwise.**
We're studying modern JavaScript after all. But you'll also see notes about how things work without `use strict`, just in case you come across an old script.

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="392" height="192" viewBox="0 0 392 192"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="v2" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="variable-change.svg"><g id="noun_1211_cc" transform="translate(52 -5)"><path id="Shape" fill="#E8C48F" d="M25 94.196h112.558v42.95c0 .373-.079.862-.279 1.294-.2.433-16.574 35.56-16.574 35.56v-54.36l16.854-25.444L156 66H43.44L25 94.196zM25 123V95l-15 28"/><g id="Rectangle-5-+-&quot;World!&quot;" transform="translate(0 57)"><path id="Rectangle-5" fill="#FFF9EB" stroke="#8A704D" stroke-width="2" d="M18.861 1.809L2 17.533l53.14 56.986L72 58.794 18.861 1.81z"/><text id="&quot;World!&quot;" fill="#8A704D" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold" transform="rotate(47 40.083 39.762)"><tspan x="10.591" y="46.262">&quot;World!&quot;</tspan></text></g><g id="Rectangle-5-+-&quot;World!&quot;-2" transform="rotate(-67 96.824 -33.912)"><path id="Rectangle-5" fill="#FFF9EB" stroke="#8A704D" stroke-width="2" d="M18.861 1.809L2 17.533l53.14 56.986L72 58.794 18.861 1.81z"/><text id="&quot;Hello!&quot;" fill="#8A704D" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold" transform="rotate(47 40.083 39.762)"><tspan x="10.591" y="46.262">&quot;Hello!&quot;</tspan></text></g><path id="Shape" fill="#E8C48F" d="M8 125v54.73c0 3.42 1.484 5.27 4.387 5.27h100.086c3.122 0 5.527-2.548 5.527-3.476V125H8z"/></g><text id="message" fill="#FFF" font-family="OpenSans-Bold, Open Sans" font-size="18" font-weight="bold"><tspan x="77" y="157">message</tspan></text><path id="Fill-54" fill="#E8C48F" d="M58.112 51.808S47.657 40.623 40.719 36.155l-.505 5.542a76.036 76.036 0 00-33.769 4.595l4.169 11.032a64.248 64.248 0 0128.531-3.882l-.505 5.542c5.581-3.329 19.472-7.176 19.472-7.176" transform="rotate(11 32.278 47.57)"/><path id="Fill-54" fill="#E8C48F" d="M287.797 28.186s-10.454-11.185-17.393-15.653l-.505 5.541a76.036 76.036 0 00-33.769 4.596l4.169 11.032a64.248 64.248 0 0128.531-3.882l-.504 5.541c5.58-3.328 19.47-7.175 19.47-7.175" transform="rotate(2 261.964 23.947)"/><g id="noun_48910_cc" transform="translate(298 5)"><path id="Shape" d="M50.983 6H36.016C35.456 6 35 6.626 35 7.395V12h17V7.395C52 6.626 51.543 6 50.983 6z"/><path id="Shape" fill="#E8C48F" d="M84.193 9.36h-26.39V6.085C57.803 2.729 54.99 0 51.528 0H36.47c-3.46 0-6.275 2.729-6.275 6.085V9.36H3.807C1.705 9.36 0 11.012 0 13.05v.26C0 15.348 1.705 17 3.807 17h80.386C86.295 17 88 15.348 88 13.31v-.26c0-2.038-1.706-3.69-3.807-3.69zM53 12H36V7.395C36 6.626 36.457 6 37.016 6h14.968C52.544 6 53 6.626 53 7.395V12zM74.955 20.045H8.044c-3.89 0-7.044-.68-7.044 3.266l5.282 78.382c0 3.943 3.155 7.307 7.045 7.307h56.347c3.89 0 7.044-3.364 7.044-7.307L82 23.31c-.001-3.947-3.155-3.266-7.045-3.266zM26.757 98.999c-1.283.039-2.353-.8-2.396-1.878l-2.36-61.095c-.041-1.078.964-1.985 2.242-2.025 1.283-.04 2.353.801 2.396 1.879l2.36 61.096c.041 1.076-.963 1.984-2.242 2.023zM43 97.049C43 98.126 42.328 99 41.5 99s-1.5-.876-1.5-1.951V35.95c0-1.078.672-1.951 1.5-1.951s1.5.873 1.5 1.951V97.05zm18.639.072c-.042 1.078-1.113 1.917-2.396 1.878-1.28-.04-2.283-.947-2.242-2.024l2.36-61.095c.042-1.078 1.112-1.919 2.394-1.879 1.28.042 2.285.947 2.244 2.025l-2.36 61.095z"/></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 3.6 KiB

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="359" height="143" viewBox="0 0 359 143"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="v2" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="variable-copy-value.svg"><g id="noun_1211_cc-+-Message" transform="translate(11 6)"><g id="noun_1211_cc"><path id="Shape" fill="#E8C48F" d="M17 37.196h112.558v42.95c0 .373-.079.862-.279 1.294-.2.433-16.574 35.56-16.574 35.56V62.64l16.854-25.444L148 9H35.44L17 37.196zM17 66V38L2 66"/><g id="Rectangle-5-+-&quot;World!&quot;" transform="translate(15)"><path id="Rectangle-5" fill="#FFF9EB" stroke="#8A704D" stroke-width="2" d="M18.861 1.809L2 17.533l53.14 56.986L72 58.794 18.861 1.81z"/><text id="&quot;Hello!&quot;" fill="#8A704D" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold" transform="rotate(47 38.202 38.946)"><tspan x="2.822" y="43.482">&quot;Hello!&quot;</tspan></text></g><path id="Shape" fill="#E8C48F" d="M0 68v54.73c0 3.42 1.484 5.27 4.387 5.27h100.086c3.122 0 5.527-2.548 5.527-3.476V68H0z"/></g><text id="message" fill="#FFF" font-family="OpenSans-Bold, Open Sans" font-size="18" font-weight="bold"><tspan x="17" y="105">message</tspan></text></g><g id="Group" transform="translate(210 6)"><path id="Shape" fill="#E8C48F" d="M17 37.196h113.417v42.95c0 .373-.08.862-.28 1.294-.202.433-16.702 35.56-16.702 35.56V62.64l16.983-25.444L149 9H35.582L17 37.196z"/><path id="Shape" fill="#E8C48F" d="M18 66V38L2 66"/><g id="Rectangle-5-+-&quot;World!&quot;" transform="translate(15)"><path id="Rectangle-5" fill="#FFF9EB" stroke="#8A704D" stroke-width="2" d="M19.117 1.8l-17.1 15.734 53.866 56.994 17.1-15.734L19.118 1.799z"/><text id="&quot;Hello!&quot;" fill="#8A704D" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold" transform="rotate(47 38.162 37.693)"><tspan x="2.782" y="42.23">&quot;Hello!&quot;</tspan></text></g><path id="Shape" fill="#E8C48F" d="M0 68v54.73c0 3.42 1.497 5.27 4.427 5.27h100.996c3.15 0 5.577-2.548 5.577-3.476V68H0z"/><text id="hello" fill="#FFF" font-family="OpenSans-Bold, Open Sans" font-size="18" font-weight="bold"><tspan x="25" y="105">hello</tspan></text></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="166" height="145" viewBox="0 0 166 145"><defs><style>@import url(https://fonts.googleapis.com/css?family=Open+Sans:bold,italic,bolditalic%7CPT+Mono);@font-face{font-family:&apos;PT Mono&apos;;font-weight:700;font-style:normal;src:local(&apos;PT MonoBold&apos;),url(/font/PTMonoBold.woff2) format(&apos;woff2&apos;),url(/font/PTMonoBold.woff) format(&apos;woff&apos;),url(/font/PTMonoBold.ttf) format(&apos;truetype&apos;)}</style></defs><g id="v2" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="variable.svg"><g id="noun_1211_cc-+-Message" transform="translate(13 3)"><g id="noun_1211_cc"><path id="Shape" fill="#E8C48F" d="M17 37.196h112.558v42.95c0 .373-.079.862-.279 1.294-.2.433-16.574 35.56-16.574 35.56V62.64l16.854-25.444L148 9H35.44L17 37.196zM17 66V38L2 66"/><g id="Rectangle-5-+-&quot;World!&quot;" transform="translate(15)"><path id="Rectangle-5" fill="#FFF9EB" stroke="#8A704D" stroke-width="2" d="M18.861 1.809L2 17.533l53.14 56.986L72 58.794 18.861 1.81z"/><text id="&quot;Hello!&quot;" fill="#8A704D" font-family="OpenSans-Bold, Open Sans" font-size="14" font-weight="bold" transform="rotate(47 40.083 39.762)"><tspan x="10.591" y="46.262">&quot;Hello!&quot;</tspan></text></g><path id="Shape" fill="#E8C48F" d="M0 68v54.73c0 3.42 1.484 5.27 4.387 5.27h100.086c3.122 0 5.527-2.548 5.527-3.476V68H0z"/></g><text id="message" fill="#FFF" font-family="OpenSans-Bold, Open Sans" font-size="18" font-weight="bold"><tspan x="17" y="105">message</tspan></text></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB