minor fixes

This commit is contained in:
Ilya Kantor 2021-06-09 07:07:18 +03:00
parent 5a024624af
commit d20a6e3d5e
33 changed files with 357 additions and 395 deletions

View file

@ -1,44 +1,23 @@
# Hello, JavaScript!
JavaScript has a rich history.
It was created in 1995 as a simple language exclusively for web browsers, to “make web pages alive”. Since then it has greatly evolved.
JavaScript was created in 1995 as a simple language exclusively for web browsers, to "make web pages alive". Since then it has greatly evolved, it's quite far from there it started.
Today we can use JavaScript on many platforms:
- In a web-browser, by embedding it into a web page.
- On a general purpose computer or a server, using [Node.js](https://nodejs.org) and other means.
- ...Or actually on any device that has a special piece of software, called "JavaScript engine".
- ...Or actually on any device that has a special piece of software, called "a JavaScript engine".
Technically, even a coffee machine can include its own JavaScript engine to allow programming of coffee recipes.
![](javascript-engine.svg)
There's a formal language description called [ECMAScript Language Specification](https://tc39.es/ecma262/), it describes how a JavaScript engine works. Sometimes we'll give references to it, but, though technically strict, it's hard to read for humans. At least at first.
There's a formal language description called [ECMAScript Language Specification](https://tc39.es/ecma262/), it describes how a JavaScript engine works. Sometimes we'll give references to it, but, though technically correct, it's hard to read for humans.
Programs in JavaScript are called *scripts*.
Programs in JavaScript are called "scripts".
Browsers have built-in JavaScript engines, so they can run scripts. They can be embedded right into HTML using the `<script>` tag and run automatically as the page loads.
**In this tutorial we concentrate on the "core" JavaScript, that works mostly everywhere.**
For example, this HTML-page shows the "Hello, world!" message:
```html run height=0
<!doctype html>
<script>
alert("Hello, world!");
</script>
```
To see it in action, you can click the "run" button in the upper-right corner. Also you can create a new file, e.g. `my.html` with this text and open it locally in a browser.
Depending on the environment, JavaScript may provide platform-specific functionality.
- In a browser, JavaScript can manipulate the web-page, send network requests, show messages and so on.
- In node.js we can use JavaScript to run a web-server, read and write arbitrary files.
- ...And so on.
**In this course we concentrate on the core JavaScript, that's the same everywhere.**
We'll try to keep browser-specific notes at minimum. After you learn the core, you can go in any direction: browsers, frameworks, servers and so on.
Then, after you're familiar with it, you'll be able to move in any direction: browsers, servers and so on.
Turn the page to start learning JavaScript!

View file

@ -1,197 +0,0 @@
# Code structure
## Statements
Just like a human speech consists of sentences, JavaScript code consists of *statements*.
Statements are commands and syntax constructs that perform actions, "do" something.
Here's an example of a statement:
```js run
alert("Hello, world!");
```
Click the "run" icon ▷ in the right-upper corner to see how it works.
We can have as many statements in our code as we want.
Statements can be separated with a semicolon.
For example, we can split "Hello World" into two messages, one after the other:
```js run no-beautify
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");
```
### Semicolons..or not?
A semicolon may be omitted in most cases when a line break exists beween statements.
This code is the same as above, just without semicolons:
```js run no-beautify
alert("Hello")
alert("World")
```
It also works, because usually JavaScript interprets a line break as an "implicit" semicolon. This is called an "automatic semicolon insertion".
There are exceptions for that rule, for example:
```js run no-beautify
alert(1 +
2);
```
This code outputs `3`, same as a single-line `alert(1 + 2)`. Here JavaScript does not treat the line-break after `+` as the end of the statement.
Why so? It's intuitively obvious that if the line ends with a plus `+`, then the expression is incomplete and will be continued on the next line. JavaScript "understands" that too. And in this case that works as intended.
**But there are situations where our intuition differs from JavaScript auto-insertion rules.**
That may lead to subtle errors.
````spoiler header="See an example of such error"
If you're curious to see a concrete example of such an error, check this code out:
```js run
[1, 2].forEach(alert)
```
The code may be too advanced to understand right now, but that's all right.
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 the alert - error")
[1, 2].forEach(alert)
```
Now if you run the code, only the first `alert` is shown and then there's an error!
...But everything becomes fine again we add a semicolon after the `alert`:
```js run
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 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:
```js run no-beautify
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.
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
As time goes on, programs become more and more complex. It becomes necessary to add *comments* which describe what the code does and why.
Comments can be put into any place of a script. They don't affect its execution because the engine simply ignores them.
**One-line comments start with two forward slash characters `//`. The rest of the line is a comment.**
Such comment may occupy a full line of its own or follow a statement.
Like here:
```js run
// This comment occupies a line of its own
alert("Hello");
alert("World"); // This comment follows the statement
```
For longer, descriptive comments that span multiple lines, we can use the `/* ... */` syntax.
**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>.**
Like this:
```js run
/* An example with two messages.
This is a multiline comment.
*/
alert("Hello");
alert("World");
```
The content of comments is ignored, so if we wrap a piece of code into `/* ... */`, it won't execute.
It can be handy to temporarily disable a part of code:
```js run
/* Commenting out the code
alert("Hello");
*/
alert("World");
```
```smart header="Use hotkeys!"
In most editors, a line of code can be commented out by pressing the `key:Ctrl+/` hotkey for a single-line comment and something like `key:Ctrl+Shift+/` -- for multiline comments (select a piece of code and press the hotkey).
For Mac, try `key:Cmd` instead of `key:Ctrl` and `key:Option` instead of `key:Shift`.
```
````warn header="Nested comments are not supported!"
There may not be `/*...*/` inside another `/*...*/`.
Such code will die with an error:
```js run no-beautify
/*
/* nested comment leads to an error! */
*/
alert( "World" );
```
````
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.
## Strict mode
JavaScript appeared in 1995 as a simple, browser-only language. 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 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 about it.
**To keep the old code working, the newer 2009+ modifications are off by default.**
Yes, a lot of time has passed, but still it's so.
We need to explicitly enable them with a special directive: `"use strict"`
A script with the `"use strict"` directive on top 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 forget to put that directive or meet a script without it.

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="196" height="129" viewBox="0 0 196 129"><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="use-strict.svg"><g id="noun_Cloud_3562756" fill="#000" fill-rule="nonzero" transform="translate(36 14)"><path id="Path" d="M32.236 42.259a38.415 38.415 0 01-8.566.951C10.596 43.208.003 36.98 0 29.297c.003-7.684 10.596-13.91 23.67-13.91 3.684 0 7.168.501 10.272 1.386C35.919 7.32 49.589.002 66.207 0c15.85.002 29.019 6.662 31.92 15.48.875-.06 1.766-.094 2.672-.094V17.383a32.79 32.79 0 00-3.75.217c-.461.051-.93-.008-1.309-.17-.384-.158-.635-.4-.698-.673C93.07 8.42 80.927 1.997 66.205 2 50.505 1.998 37.738 9.3 37.116 18.44c-.027.355-.372.68-.912.844a2.77 2.77 0 01-1.699-.041c-3.147-1.173-6.847-1.86-10.838-1.86-11.194.01-20.248 5.333-20.268 11.913.02 6.583 9.074 11.903 20.271 11.916 3.294 0 6.383-.472 9.14-1.29a2.763 2.763 0 011.59.016c.491.16.817.45.87.78.837 5.206 8.3 9.287 17.383 9.287 6.236 0 11.69-1.93 14.788-4.826.247-.23.64-.391 1.09-.444a2.692 2.692 0 011.3.145c2.042.806 4.485 1.276 7.131 1.276 6.202.004 11.367-2.6 12.533-6.04.107-.306.45-.568.924-.704a2.804 2.804 0 011.508.004c2.684.792 5.682 1.245 8.875 1.245 10.932-.012 19.779-5.211 19.8-11.638-.021-6.43-8.868-11.63-19.803-11.642V15.385c12.812 0 23.198 6.105 23.201 13.638-.003 7.531-10.389 13.633-23.201 13.635-3.01 0-5.883-.346-8.515-.96-2.168 3.755-8.206 6.453-15.324 6.455-2.734 0-5.318-.401-7.579-1.106-3.798 3-9.872 4.953-16.728 4.953-10.055-.001-18.438-4.177-20.417-9.741z"/></g><text id="&quot;use-strict&quot;" fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="45.1" y="47">&quot;use strict&quot;</tspan></text><text id="...modern-code..." fill="#8A704D" font-family="PTMono-Regular, PT Mono" font-size="14" font-weight="normal"><tspan x="24.6" y="94">...modern code...</tspan></text></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -0,0 +1 @@
console.log("It works");

View file

@ -0,0 +1,5 @@
Congratulations!
This task was simple though.
Go ahead to learn more.

View file

@ -0,0 +1,11 @@
# Hello, world!
Welcome to the tasks!
Practicing will help you to understand theory and hone your skills!
The first task is simple, just to get acquainted.
Write the code to `console.log` a message "Hello" (you actually saw the correct right in the tutorial).

View file

@ -0,0 +1,7 @@
// TODO: tests are executed after code (See evalWorker.js)
//
window.addEventListener('message', event => {
// event.name = message or log or whatever?
// check that console.log happened
console.error(event);
});

View file

@ -0,0 +1,131 @@
# Statements
Just like a human speech consists of sentences, JavaScript code consists of *statements*.
Here's an example of a statement:
```js run
console.log("Hello, world!");
```
Click the "run" icon ▷ in the right-upper corner to see how it works.
In this particular statement `console.log` is the command to show a message, and `"Hello, world!"` is the string to show. We'll learn more about commands and strings soon.
We can have as many statements as we want.
For example, let's make it two separate messages, one after the other:
```js run
console.log("Hello"); console.log("World");
```
Usually, statements are written on separate lines to make the code more readable, like this:
```js run no-beautify
console.log("Hello");
console.log("World");
```
Please note: every statement ends with a semicolon `;`.
## Semicolons..or not?
Technically, a semicolon may be unnecessary, if there's a line break between statements.
Here's the same code as above, but without semicolons:
```js run no-beautify
console.log("Hello")
console.log("World")
```
It also works, because usually JavaScript interprets a line break as an "implicit" semicolon. This language feature is called the "semicolon auto-insertion".
There are exceptions for that auto-insertion, for example:
```js run no-beautify
console.log(1 +
2);
```
This code outputs `3`, same as a single-line `console.log(1 + 2)`. Here JavaScript assumes that the line-break after `+` doesn't end the statement.
Why so? For us humans, it's intuitively obvious that if the line ends with a plus `+`, then the expression is incomplete and will be continued on the next line. JavaScript has internal grammar rules for that.
Although, these rules aren't perfect.
**There are situations where our intuition differs from JavaScript semicolon auto-insertion rules.**
That may lead to subtle errors.
To prevent them, we recommend putting semicolons between statements, even if they are separated by newlines. Most of the JavaScript codebase follows this convention.
````spoiler header="See an example of such error"
If you're curious to see a concrete example of such an error, check this code out:
```js run
console.log("Hello");
[1, 2].forEach(console.log);
```
That's some advanced code, but noo need to think about the meaning of the brackets `[]` and `forEach` yet. Well study them later.
For now just remember the result of running the code: it shows `Hello`, then `1`, then `2`.
Now lets remove one semicolon after the console.log, and see how it fails:
```js run
console.log("Hello")
[1, 2].forEach(console.log);
```
The difference compared to the code above is only one character: the semicolon at the end of the first line is gone.
If we run this code, only the first `Hello` shows, and then there's an error. There are no numbers any more!
That's because JavaScript doesn't auto-insert a semicolon before square brackets [...]. So, the code in the last example is treated as a single statement, as if there were no line break at all.
In other words, JavaScript
```js
console.log("Hello")[1, 2].forEach(console.log);
```
The code may be too advanced to understand right now, but that's all right.
All you need to do is to run the code and remember the result: it shows `1` then `2`.
Let's add an `console.log` before the code and *not* finish it with a semicolon:
```js run no-beautify
console.log("Without a semicolon after the console.log - error")
[1, 2].forEach(console.log)
```
Now if you run the code, only the first `console.log` is shown and then there's an error!
...But everything becomes fine again we add a semicolon after the `console.log`:
```js run
console.log("With a semicolon after me - all ok");
[1, 2].forEach(console.log)
```
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:
```js run no-beautify
console.log("There will be an error")[1, 2].forEach(console.log)
```
But such a merge in this case is just wrong, hence the error. This can happen in other situations as well.
````
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.

View file

@ -0,0 +1,66 @@
# Comments
As time goes on, scripts tend to become more complex. We can add *comments* to describe what the code does and why.
Comments can be put into any place of a script. They don't affect its execution because the engine simply ignores them.
**One-line comments start with two forward slash characters `//`. The rest of the line is a comment.**
Such comment may occupy a full line of its own or follow a statement.
Like here:
```js run
// This comment occupies a line of its own
console.log("Hello");
console.log("World"); // This comment follows the statement
```
For longer, descriptive comments that span multiple lines, we can use the `/* ... */` syntax.
**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>.**
Like this:
```js run
/* An example with two messages.
This is a multiline comment.
*/
console.log("Hello");
console.log("World");
```
The content of comments is ignored, so if we wrap a piece of code into `/* ... */`, it won't execute.
It can be handy to temporarily disable ("comment out") a part of code:
```js run
/* Commenting out the code
console.log("Hello");
*/
console.log("World");
```
```smart header="Use hotkeys!"
In most editors, a line of code can be commented out by pressing the `key:Ctrl+/` hotkey for a single-line comment and something like `key:Ctrl+Shift+/` -- for multiline comments (select a piece of code and press the hotkey).
For Mac, try `key:Cmd` instead of `key:Ctrl` and `key:Option` instead of `key:Shift`.
```
````warn header="Nested comments are not supported!"
There may not be `/*...*/` inside another `/*...*/`.
Such code will die with an error:
```js run no-beautify
/*
/* nested comment leads to an error! */
*/
console.log( "World" );
```
````
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.

View file

@ -1,3 +0,0 @@
let user, admin;
user = "John";

View file

@ -1,21 +0,0 @@
## The variable for our planet
That's simple:
```js
let ourPlanetName = "Earth";
```
Note, we could use a shorter name `planet`, but it might be not obvious what planet it refers to. It's nice to be more verbose. At least until the variable isNotTooLong.
## The name of the current visitor
```js
let currentUserName = "John";
```
Again, we could shorten that to `userName` if we know for sure that the user is current.
Modern editors and autocomplete make long variable names easy to write. Don't save on them. A name with 3 words in it is fine.
And if your editor does not have proper autocompletion, get [a new one](/code-editors).

View file

@ -1,8 +0,0 @@
importance: 3
---
# Giving the right name
1. Create a variable with the name of our planet. How would you name such a variable?
2. Create a variable to store the name of a current visitor to a website. How would you name that variable?

View file

@ -1,5 +0,0 @@
We generally use upper case for constants that are "hard-coded". Or, in other words, when the value is known prior to execution and directly written into the code.
In this code, `birthday` is exactly like that. So we could use the upper case for it.
In contrast, `age` is evaluated in run-time. Today we have one age, a year after we'll have another one. It is constant in a sense that it does not change through the code execution. But it is a bit "less of a constant" than `birthday`: it is calculated, so we should keep the lower case for it.

View file

@ -1,24 +0,0 @@
importance: 4
---
# Uppercase const?
Examine the following code:
```js
const birthday = '18.04.1982';
const age = someCode(birthday);
```
Here we have a constant `birthday` date and the `age` is calculated from `birthday` with the help of some code (it is not provided for shortness, and because details don't matter here).
Would it be right to use upper case for `birthday`? For `age`? Or even for both?
```js
const BIRTHDAY = '18.04.1982'; // make uppercase?
const AGE = someCode(BIRTHDAY); // make uppercase?
```

View file

@ -0,0 +1,2 @@
let admin;
let user;

View file

@ -0,0 +1,4 @@
let user;
let admin;
user = "John";

View file

@ -1,5 +1,5 @@
describe("Test", function() {
it(`user equals "John"`, function() {
it(`user has a value: "John"`, function() {
expect(user).toEqual("John");
});
});

View file

@ -1,5 +1,5 @@
describe("Test", function() {
it(`user and admin equal "John"`, function() {
it(`user and admin have value "John"`, function() {
expect(user).toEqual("John");
expect(admin).toEqual("John");
});

View file

@ -1,19 +1,13 @@
# Variables
To do its job, our code needs needs to store and process information.
The exact kind of information depends on the application.
Depending on our application, scripts need to store and manipulate different kinds of data.
For example:
- An online shop -- the information includes goods being sold and a shopping cart.
- A chat application -- the information includes users, messages, etc.
- An online shop -- the data includes goods being sold and the shopping cart content.
- A chat application -- the data includes users, messages, etc.
Variables are used to store this information.
## A variable
A [variable](https://en.wikipedia.org/wiki/Variable_(computer_science)) is a "named storage" for data. We can use variables to store goods, visitors and so on.
A [variable](https://en.wikipedia.org/wiki/Variable_(computer_science)) is a "named storage" for data.
To create a variable in JavaScript, use the `let` keyword.
@ -23,7 +17,7 @@ The statement below creates (in formal terms: *declares*) a variable with the na
let message;
```
Now we can put some data into it by using the assignment `=`:
Now we can store some data into it by using the assignment `=`:
```js
let message;
@ -40,25 +34,27 @@ let message;
message = "Hello!";
*!*
alert(message); // shows the variable content
console.log(message); // shows the variable content
*/!*
```
To be concise, we can combine the variable declaration and assignment into a single line:
```js run
let message = "Hello!"; // define the variable and assign the value to it
*!*
let message = "Hello!"; // declare the variable and assign the value to it
*/!*
alert(message); // Hello!
console.log(message); // Hello!
```
We can also declare multiple variables in one line:
One can also declare multiple variables in one line:
```js no-beautify
let user = "John", age = 25, message = "Hello";
```
That might seem shorter, but we don't recommend it. For the sake of better readability, please use a single line per variable.
That might seem shorter, but we don't recommend it. For the sake of better readability, it's better to use a single line per variable.
The multiline variant is a bit longer, but easier to read:
@ -68,38 +64,9 @@ let age = 25;
let message = "Hello";
```
Some people also define multiple variables in this multiline style:
```js no-beautify
let user = "John",
age = 25,
message = "Hello";
```
...Or even in the "comma-first" style:
```js no-beautify
let user = "John"
, age = 25
, message = "Hello";
```
Technically, all these variants do the same thing. So, it's a matter of personal taste and aesthetics.
````smart header="`var` instead of `let`"
In older scripts, you may also find another keyword: `var` instead of `let`:
```js
*!*var*/!* message = "Hello";
```
The `var` keyword is *almost* the same as `let`. It also declares a variable, but in a slightly different, "old-school" way.
There are subtle differences between `let` and `var`, but they do not matter for us now. We'll cover them in the optional chapter <info:var>. We should never use `var` in modern scripts.
````
## A real-life analogy
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.
We can easily grasp the concept of a "variable" if we imagine it as a "box" for data, with a named sticker on it.
For instance, the variable `message` can be imagined as a box labeled `"message"` with the value `"Hello!"` in it:
@ -108,6 +75,7 @@ For instance, the variable `message` can be imagined as a box labeled `"message"
We can put any value in the box.
We can also change it as many times as we want:
```js run
let message;
@ -115,7 +83,7 @@ message = "Hello!";
message = "World!"; // value changed
alert(message);
console.log(message);
```
When the value is changed, the old data is removed from the variable:
@ -135,8 +103,8 @@ message = hello;
*/!*
// now two variables hold the same data
alert(hello); // Hello world!
alert(message); // Hello world!
console.log(hello); // Hello!
console.log(message); // Hello!
```
Now we have two variables, both store the same string:
@ -158,43 +126,20 @@ 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="Without `use strict`: it's possible to assign to an undeclared variable"
Normally, we need to define a variable before using it. But in the old times, it was technically possible to create a variable by a mere assignment of the value without using `let`.
## Variable naming
This still works now, without strict mode:
Technically, a variable name can be any word.
```js run no-strict
// note: no "use strict" in this example
There's just a couple of limitations:
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:
```js
"use strict";
*!*
num = 5; // error: num is not defined
*/!*
```
We provide details about how things work without `use strict` just to make sure you won't be surprised by such scripts. Luckily, there aren't many differences. As said before, we should always be in the 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 `_`.
1. The name must be made of letters, digits, or symbols `$` and `_`.
2. The first character must not be a digit.
Examples of valid names:
```js
let userName;
let test123;
```
@ -208,7 +153,7 @@ These names are valid:
let $ = 1; // declared a variable with the name "$"
let _ = 2; // and now a variable with the name "_"
alert($ + _); // 3
console.log($ + _); // 3
```
Examples of incorrect variable names:
@ -249,30 +194,37 @@ let return = 5; // also can't name it "return", error!
## Constants
To declare a constant (unchanging) variable, use `const` instead of `let`:
There are information pieces that aren't expected to change.
For example, a date of birth is a fixed point of time.
To declare a variable that isn't expected to change, use `const` instead of `let`:
```js
const myBirthday = '18.04.1982';
const myBirthdate = '18.04.1982';
```
Variables declared using `const` are called "constants". They cannot be reassigned. An attempt to do so would cause an error:
```js run
const myBirthday = '18.04.1982';
const myBirthdate = '18.04.1982';
myBirthday = '01.01.2001'; // error, can't reassign the constant!
myBirthdate = '01.01.2001'; // error, can't reassign the constant!
```
When a programmer is sure that a variable will never change, they can declare it with `const` to guarantee and clearly communicate that fact to everyone.
Here's why using `const` for such variables is a good thing.
1. It gives a hint to every person who reads the code, that the value isn't going to change. So that they can safely eye-jump while reading the code and assume it's still the same.
2. It insures against programming mistakes: if we (or another person who supports our code) attempt to change it, there'll be an error.
### Uppercase constants
## Uppercase constants
There is a widespread practice to use constants as aliases for difficult-to-remember values that are known prior to execution.
Such constants are named using capital letters and underscores.
For instance, let's make constants for colors in so-called "web" (hexadecimal) format:
For instance, let's make constants for hexadecimal color codes (these codes are used in web programming and other areas):
```js run
const COLOR_RED = "#F00";
@ -280,27 +232,28 @@ const COLOR_GREEN = "#0F0";
const COLOR_BLUE = "#00F";
const COLOR_ORANGE = "#FF7F00";
// ...when we need to pick a color
let color = COLOR_ORANGE;
alert(color); // #FF7F00
// ...when we need to pick a color:
let color = COLOR_ORANGE; // (instead of the hexadecimal code)
console.log(color); // #FF7F00
```
Benefits:
- `COLOR_ORANGE` is much easier to remember than `"#FF7F00"`.
- It is much easier to mistype `"#FF7F00"` than `COLOR_ORANGE`.
- It is much easier to mistype `"#FF7F00"` than `COLOR_ORANGE`, so it's also more reliable.
- When reading the code, `COLOR_ORANGE` is much more meaningful than `#FF7F00`.
When should we use capitals for a constant and when should we name it normally? Let's make that clear.
Being a "constant" just means that a variable's value never changes. But there are constants that are known prior to execution (like a hexadecimal value for red) and there are constants that are *calculated* in run-time, during the execution, but do not change after their initial assignment.
Being a "constant" just means that a variable's value never changes. But there are constants that are known prior to execution (like a hexadecimal value for the orange color) and there are constants that are *calculated* in run-time, during the execution, but do not change after their initial assignment.
For instance:
```js
const pageLoadTime = /* time taken by a webpage to load */;
const currentDate = /* assign the current date here */;
```
The value of `pageLoadTime` is not known prior to the page load, so it's named normally. But it's still a constant because it doesn't change after assignment.
The value of `currentDate` is a constant because it doesn't change after assignment, but it may differ from day to day. So it's lowercased.
In other words, capital-named constants are only used as aliases for "hard-coded" values, known prior to execution.
@ -325,24 +278,14 @@ Some good-to-follow rules are:
Sounds simple? Indeed it is, but creating descriptive and concise variable names in practice is not. Go for it.
```smart header="Reuse or create?"
And the last note. There are some lazy programmers who, instead of declaring new variables, tend to reuse existing ones.
```smart header="Create, don't reuse"
And the last note. There are some lazy programmers who, instead of declaring new variables, tend to reuse existing ones, write new values into them.
As a result, their variables are like boxes into which people throw different things without changing their stickers. What's inside the box now? Who knows? We need to come closer and check.
Such programmers save a little bit on variable declaration but lose ten times more on debugging.
Such programmers save a little bit when writing code, but lose ten times more when reading it.
An extra variable is good, not evil.
Modern JavaScript minifiers and browsers optimize code well enough, so it won't create performance issues. Using different variables for different values can even help the engine optimize your code.
Modern JavaScript tools and browsers optimize code well enough, so it won't create performance issues. Using different variables for different values can even help the engine optimize your code.
```
## Summary
We can declare variables to store data by using the `var`, `let`, or `const` keywords.
- `let` -- is a modern variable declaration.
- `var` -- is an old-school variable declaration. Normally we don't use it at all, but we'll cover subtle differences from `let` in the chapter <info:var>, just in case you need them.
- `const` -- is like `let`, but the value of the variable can't be changed.
Variables should be named in a way that allows us to easily understand what's inside them.

View file

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Before After
Before After

View file

@ -0,0 +1,73 @@
# Strict mode
JavaScript appeared in 1995 as a simple, browser-only language. 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 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. Also made some syntax more strict.
Now the important part about it.
**To avoid breaking the old code, the newer modifications and restrictions are off by default.**
The good thing is: there aren't many such modifications. Also, newly introduced language features do work. The disabled things are only those that were *changed* in the language in a way that may break the code written before them.
For example, in dark old times JavaScript allowed variables to be assigned without a declaration.
Like this:
```js no-strict
*!*
user = "John";
*/!*
console.log(user); // John
```
As we can see, it should be `let user`. But JavaScript was forgiving.
This feature of the language was frowned upon, because it made code more error-prone.
Imagine, if you have a variable named `user`, and then mistype, e.g. assign to `usr` instead:
```js no-strict
let user;
usr = "John"; // mistype!
// (technically, not an error, a new variable usr is created)
```
After 2009, the language started to protect against such mistypes by requiring all variables to be declared and triggering an error otherwise.
Although, as there were many old scripts, to keep them functioning, this change, along with others, is off by default.
## Use strict
To enable all the modern changes, we need to start a script with a special directive: `"use strict"`.
Like this:
```js
"use strict";
console.log("This script works in the strict mode");
```
Please note: the directive must be at the very top, only comments are allowed above it.
With `"use strict"`, a mistype in the variable name causes an error:
```js no-strict
"use strict";
let user;
usr = "John"; // Error
```
In the future, when we learn some advanced language features (such as classes and modules), you'll see that they enable strict mode automatically. Until then, it's a good rule to start scripts with `"use strict"`.
**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`, so that you're aware, just in case you forget to put that directive or meet a script without it.