en
This commit is contained in:
parent
48497f7d85
commit
8ba2c6b17c
23 changed files with 574 additions and 615 deletions
|
@ -24,7 +24,7 @@ Open the page [bug.html](bug.html).
|
|||
|
||||
There's an error in the JavaScript code on it. An ordinary visitor won't see it, we need t open developer tools for that.
|
||||
|
||||
Press the keys [key Ctrl+Shift+J] or, if you're on Mac, then [key Cmd+Shift+J].
|
||||
Press the key [key F12] or, if you're on Mac, then [key Cmd+Opt+J].
|
||||
|
||||
The developer tools will open on the Console tab by default.
|
||||
|
||||
|
@ -51,7 +51,7 @@ It is done on the "Advanced" pane of the preferences:
|
|||
|
||||
<img src="safari.png">
|
||||
|
||||
Now [key Cmd+Alt+C] can toggle on the console. Also the new top menu item has appeared with many useful options.
|
||||
Now [key Cmd+Opt+C] can toggle the console. Also the new top menu item has appeared with many useful options.
|
||||
|
||||
## Other browsers
|
||||
|
||||
|
@ -62,10 +62,8 @@ The look & feel of them is quite similar, once we know how to use one of them (c
|
|||
## Summary
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Developer tools allow us to see errors (crucial now), run commands, examine variables and much more.</li>
|
||||
<li>
|
||||
They can be opened with [key F12] for most browsers, with the exception of Chrome ([key Ctrl+Shift+J] / [key Cmd+Shift+J]) and Safari (need to enable, then [key Cmd+Alt+C]).
|
||||
<li>Developer tools allow us to see errors (crucial now), run commands, examine variables and much more.</li>
|
||||
<li>They can be opened with [key F12] for most browsers under Windows. Chrome for Mac needs [key Cmd+Opt+J], Safari: [key Cmd+Opt+C] (need to enable first).
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
Код страницы:
|
||||
|
||||
```html
|
||||
<!--+ run -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script>
|
||||
alert( 'Я - JavaScript!' );
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
```
|
||||
|
|
@ -1,14 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script>
|
||||
alert('Я - JavaScript!');
|
||||
alert( "I'm JavaScript!" );
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# Выведите alert
|
||||
# Show an alert
|
||||
|
||||
[importance 5]
|
||||
|
||||
Сделайте страницу, которая выводит "Я - JavaScript!".
|
||||
Create a page that shows a message "I'm JavaScript!".
|
||||
|
||||
Создайте её на диске, откройте в браузере, убедитесь, что всё работает.
|
||||
Do it in a sandbox, or on your hard drive, doesn't matter, just ensure that it works.
|
||||
|
||||
[demo src="solution"]
|
||||
|
|
|
@ -6,89 +6,72 @@ In this chapter we'll create a simple script and see it working.
|
|||
## The "script" tag
|
||||
|
||||
[smart header="What if I want to move faster?"]
|
||||
In the case if the impatient reader developed with JavaScript already or has a lot of experience in another language, he can skip detailed explanatins and jump to [](/javascript-specials). There he can find a condensed essense of important features.
|
||||
In the case if an impatient reader has developed with JavaScript already or has a lot of experience in another language, he can skip detailed explanatins and jump to [](/javascript-specials). There he can find an essense of important features.
|
||||
|
||||
If you have enough time and want to learn things in details then read on :)
|
||||
[/smart]
|
||||
|
||||
Программы на языке JavaScript можно вставить в любое место HTML при помощи тега `SCRIPT`. Например:
|
||||
JavaScript programs can be inserted in any place of HTML with the help of the `<script>` tag.
|
||||
|
||||
For instance:
|
||||
|
||||
```html
|
||||
<!--+ run height=100 -->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<!-- Тег meta для указания кодировки -->
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<p>Начало документа...</p>
|
||||
<p>Document start...</p>
|
||||
|
||||
*!*
|
||||
<script>
|
||||
alert( 'Привет, Мир!' );
|
||||
alert( 'Hello, world!' );
|
||||
</script>
|
||||
*/!*
|
||||
|
||||
<p>...Конец документа</p>
|
||||
<p>...Document end.</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
```
|
||||
|
||||
Этот пример использует следующие элементы:
|
||||
You can run the example clicking on a "Play" button in it's right-top corner.
|
||||
|
||||
<dl>
|
||||
<dt><code><script> ... </script></code></dt>
|
||||
<dd>Тег `script` содержит исполняемый код. Предыдущие стандарты HTML требовали обязательного указания атрибута `type`, но сейчас он уже не нужен. Достаточно просто `<script>`.
|
||||
The `<script>` tag contains JavaScript code which is automatically executed when the browser meets the tag.
|
||||
|
||||
Please note the sequence:
|
||||
|
||||
Браузер, когда видит `<script>`:
|
||||
<ol>
|
||||
<li>Начинает отображать страницу, показывает часть документа до `script`</li>
|
||||
<li>Встретив тег `script`, переключается в JavaScript-режим и не показывает, а исполняет его содержимое.</li>
|
||||
<li>Закончив выполнение, возвращается обратно в HTML-режим и *только тогда* отображает оставшуюся часть документа.</li>
|
||||
<li>Browser starts to parse/show the document, makes it up to the `<script>`.</li>
|
||||
<li>When the browser meets `<script>`, it switches to the JavaScript execution mode. In this mode it executes the script. In this case `alert` command is used which shows a message.</li>
|
||||
<li>When the script is finished, it gets back to the HTML-mode, and *only then* it shows the rest of the document.</li>
|
||||
</ol>
|
||||
|
||||
Попробуйте этот пример в действии, и вы сами всё увидите.
|
||||
</dd>
|
||||
<dt>`alert(сообщение)`</dt>
|
||||
<dd>Отображает окно с сообщением и ждёт, пока посетитель не нажмёт "Ок".</dd>
|
||||
</dl>
|
||||
So, a visitor won't see the content after the script until the script finishes to execute.
|
||||
|
||||
[smart header="Кодировка и тег `META`"]
|
||||
При попытке сделать такой же файл у себя на диске и запустить, вы можете столкнуться с проблемой -- выводятся "кракозяблы", "квадратики" и "вопросики" вместо русского текста.
|
||||
|
||||
Чтобы всё было хорошо, нужно:
|
||||
<ol>
|
||||
<li>Убедиться, что в `HEAD` есть строка `<meta charset="utf-8">`. Если вы будете открывать файл с диска, то именно он укажет браузеру кодировку.</li>
|
||||
<li>Убедиться, что редактор сохранил файл именно в кодировке UTF-8, а не, скажем, в `windows-1251`.</li>
|
||||
</ol>
|
||||
|
||||
Указание кодировки -- часть обычного HTML, я упоминаю об этом "на всякий случай", чтобы не было сюрпризов при запуске примеров локально.
|
||||
[/smart]
|
||||
People say about that: "a `<script>` tag blocks rendering".
|
||||
|
||||
|
||||
## Современная разметка для SCRIPT
|
||||
## The modern markup
|
||||
|
||||
В старых скриптах оформление тега `SCRIPT` было немного сложнее. В устаревших руководствах можно встретить следующие элементы:
|
||||
In the past, `<script>` had a few necessary attributes.
|
||||
|
||||
We can find the following in the old code:
|
||||
|
||||
<dl>
|
||||
<dt>Атрибут <code><script <u>type</u>=...></code></dt>
|
||||
<dt>The `type` attribute: <code><script <u>type</u>=...></code></dt>
|
||||
|
||||
<dd>В отличие от HTML5, стандарт HTML 4 требовал обязательного указания этого атрибута. Выглядел он так: `type="text/javascript"`. Если указать другое значение `type`, то скрипт выполнен не будет.
|
||||
|
||||
В современной разработке атрибут `type` не обязателен.
|
||||
<dd>The old standard HTML4 required a script to have the type. Usually it was `type="text/javascript"`. The modern HTML standard assumes this `type` by default, no attribute is required.
|
||||
</dd>
|
||||
|
||||
<dt>Атрибут <code><script <u>language</u>=...></code></dt>
|
||||
<dd>Этот атрибут предназначен для указания языка, на котором написан скрипт. По умолчанию, язык -- JavaScript, так что и этот атрибут ставить не обязательно.</dd>
|
||||
<dt>Комментарии до и после скриптов</dt>
|
||||
<dd>В совсем старых руководствах и книгах иногда рекомендуют использовать HTML-комментарии внутри `SCRIPT`, чтобы спрятать Javascript от браузеров, которые не поддерживают его.
|
||||
<dt>The `language` attribute: <code><script <u>language</u>=...></code></dt>
|
||||
<dd>This attribute was meant to show the language of the script. Certain outdated browsers supported other languages at that time. As of now, this attribute makes no sense, the language is JavaScript by default. No need to use it.</dd>
|
||||
<dt>Comments before and after scripts.</dt>
|
||||
<dd>In the most pre-historic books and guides, `<script>` may have comments inside.
|
||||
|
||||
Выглядит это примерно так:
|
||||
Like this:
|
||||
|
||||
```html
|
||||
<!--+ no-beautify -->
|
||||
|
@ -97,9 +80,9 @@ If you have enough time and want to learn things in details then read on :)
|
|||
//--></script>
|
||||
```
|
||||
|
||||
Браузер, для которого предназначались такие трюки, очень старый Netscape, давно умер. Поэтому в этих комментариях нет нужды.
|
||||
These comments were supposed to hide the code from an old browser that did't understand a `<script>` tag. But all browsers from the past 15 years know about `<script>`, so that's a really ancient theme. Giving this for the sake of completeness only. So if you see such code somewhere you know the guide is really ancient and not worth looking into.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
Итак, для вставки скрипта мы просто пишем `<script>`, без дополнительных атрибутов и комментариев.
|
||||
In summary, we just use `<script>` to add some code to the page, without additional attributes and comments.
|
||||
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<script src="alert.js"></script>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
Код для HTML-файла:
|
||||
The HTML code:
|
||||
|
||||
```html
|
||||
<!--+ src="index.html" -->
|
||||
```
|
||||
|
||||
Для файла `alert.js` из той же директории:
|
||||
For the file `alert.js` in the same folder:
|
||||
|
||||
```js
|
||||
//+ src="alert.js"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Вывести alert внешним скриптом
|
||||
# Show an alert with an external script
|
||||
|
||||
[importance 5]
|
||||
|
||||
Возьмите решение предыдущей задачи [](/task/hello-alert) и вынесите скрипт во внешний файл `alert.js`, который расположите в той же директории.
|
||||
Take the solution of the previous task [](/task/hello-alert). Modify it by extracting the script content into an external file `alert.js`, residing in the same folder.
|
||||
|
||||
Откройте страницу и проверьте, что вывод сообщения всё ещё работает.
|
||||
Open the page, ensures that the alert works.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Ответы:
|
||||
Answers:
|
||||
<ol>
|
||||
<li>Первым выполнится `big.js`, это нормальная последовательность выполнения подряд идущих скриптов.</li>
|
||||
<li>Первым выполнится `small.js`, так как скрипты из-за `async` ведут себя совершенно независимо друг от друга, страница тоже от них не зависит.</li>
|
||||
<li>Первым выполнится `big.js`, так как скрипты, подключённые через `defer`, сохраняют порядок выполнения относительно друг друга.</li>
|
||||
<li>The first is `big.js`, that's a normal sequence for external `<script>` tags.</li>
|
||||
<li>The first is `small.js`, because `async` makes script behave independently of each other and the page. The first to loads runs first.</li>
|
||||
<li>The first is `big.js`, because "deferred" scripts keep relative execution order.</li>
|
||||
</ol>
|
|
@ -1,24 +1,24 @@
|
|||
# Какой скрипт выполнится первым?
|
||||
# Which script executes first?
|
||||
|
||||
[importance 4]
|
||||
|
||||
В примере ниже подключены два скрипта `small.js` и `big.js`.
|
||||
In the questions below, there are two scripts: `small.js` and `big.js`.
|
||||
|
||||
Если предположить, что `small.js` загружается гораздо быстрее, чем `big.js` -- какой выполнится первым?
|
||||
If we assume that `small.js` loads much faster compared to `big.js` -- which script executes first?
|
||||
|
||||
```html
|
||||
<script src="big.js"></script>
|
||||
<script src="small.js"></script>
|
||||
```
|
||||
|
||||
А вот так?
|
||||
What if we add `async`?
|
||||
|
||||
```html
|
||||
<script async src="big.js"></script>
|
||||
<script async src="small.js"></script>
|
||||
```
|
||||
|
||||
А так?
|
||||
What if we switch to `defer`?
|
||||
|
||||
```html
|
||||
<script defer src="big.js"></script>
|
||||
|
|
|
@ -1,104 +1,98 @@
|
|||
# Внешние скрипты, порядок исполнения
|
||||
# External scripts
|
||||
|
||||
Если JavaScript-кода много -- его выносят в отдельный файл, который подключается в HTML:
|
||||
If we have a lot of JavaScript code, it can be put into a separate file.
|
||||
|
||||
The script file is attached to HTML like this:
|
||||
|
||||
```html
|
||||
<script src="/path/to/script.js"></script>
|
||||
```
|
||||
|
||||
Здесь `/path/to/script.js` -- это абсолютный путь к файлу, содержащему скрипт (из корня сайта).
|
||||
Here `/path/to/script.js` is an absolute path to the file with the script (from the site root).
|
||||
|
||||
Браузер сам скачает скрипт и выполнит.
|
||||
|
||||
Можно указать и полный URL, например:
|
||||
We can give a full URL too, for instance:
|
||||
|
||||
```html
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.2.0/lodash.js"></script>
|
||||
```
|
||||
|
||||
Вы также можете использовать путь относительно текущей страницы. Например, `src="lodash.js"` обозначает файл из текущей директории.
|
||||
It is also possible to provide a path relative to the current page. For instance, `src="lodash.js"` means a file from the current folder.
|
||||
|
||||
Чтобы подключить несколько скриптов, используйте несколько тегов:
|
||||
To attach several scripts, use multiple tags:
|
||||
|
||||
```html
|
||||
<script src="/js/script1.js"></script>
|
||||
<script src="/js/script2.js"></script>
|
||||
...
|
||||
…
|
||||
```
|
||||
|
||||
[smart]
|
||||
Как правило, в HTML пишут только самые простые скрипты, а сложные выносят в отдельный файл.
|
||||
As a rule, only simplest scripts are put into HTML. More complex ones reside in separate files.
|
||||
|
||||
Браузер скачает его только первый раз и в дальнейшем, при правильной настройке сервера, будет брать из своего [кеша](http://ru.wikipedia.org/wiki/%D0%9A%D1%8D%D1%88).
|
||||
The benefit is that the browser will download it only once, and then store in its [cache](https://en.wikipedia.org/wiki/Web_cache).
|
||||
|
||||
Благодаря этому один и тот же большой скрипт, содержащий, к примеру, библиотеку функций, может использоваться на разных страницах без полной перезагрузки с сервера.
|
||||
After it, other pages which want the same script will take it from the cache instead of downloading it. So the file is actually downloaded only once.
|
||||
|
||||
That saves traffic and makes the future pages faster.
|
||||
[/smart]
|
||||
|
||||
|
||||
[warn header="Если указан атрибут `src`, то содержимое тега игнорируется."]
|
||||
[warn header="If `src` is set, the script content is ignored."]
|
||||
A single `<script>` tag may not both contain an `src` and the code.
|
||||
|
||||
В одном теге `SCRIPT` нельзя одновременно подключить внешний скрипт и указать код.
|
||||
|
||||
Вот так не cработает:
|
||||
This won't work:
|
||||
|
||||
```html
|
||||
<script *!*src*/!*="file.js">
|
||||
alert(1); // так как указан src, то внутренняя часть тега игнорируется
|
||||
alert(1); // the content is ignored, because src is set
|
||||
</script>
|
||||
```
|
||||
|
||||
Нужно выбрать: либо `SCRIPT` идёт с `src`, либо содержит код. Тег выше следует разбить на два: один -- с `src`, другой -- с кодом, вот так:
|
||||
One needs to choose: either `<script src="…">` or `<script>` with code. The example above should be split into two scripts: with `src` and with the code.
|
||||
|
||||
```html
|
||||
<script src="file.js"></script>
|
||||
<script>
|
||||
alert( 1 );
|
||||
alert(1);
|
||||
</script>
|
||||
```
|
||||
|
||||
[/warn]
|
||||
|
||||
## Асинхронные скрипты: defer/async
|
||||
## Asynchronous scripts: defer/async
|
||||
|
||||
Браузер загружает и отображает HTML постепенно. Особенно это заметно при медленном интернет-соединении: браузер не ждёт, пока страница загрузится целиком, а показывает ту часть, которую успел загрузить.
|
||||
Browser loads and shows HTML gradually as it comes. That's clearly noticeable on the slow internet connection. The browser doesn't wait for the page to load fully. It shows the part that has been loaded already, and then adds content to it as it loads.
|
||||
|
||||
Если браузер видит тег `<script>`, то он по стандарту обязан сначала выполнить его, а потом показать оставшуюся часть страницы.
|
||||
When the browser meets a `<script>` tag, it must execute it first and after that show the rest of the page.
|
||||
|
||||
Например, в примере ниже -- пока все кролики не будут посчитаны -- нижний `<p>` не будет показан:
|
||||
For example, in the code below -- until all rabbits are counted, the bottom `<p>` is not shown:
|
||||
|
||||
```html
|
||||
<!--+ run height=100 -->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<p>Начинаем считать:</p>
|
||||
<p>Let's count:</p>
|
||||
|
||||
*!*
|
||||
<script>
|
||||
alert( 'Первый кролик!' );
|
||||
alert( 'Второй кролик!' );
|
||||
alert( 'Третий кролик!' );
|
||||
alert( 'The 1st rabbit!' );
|
||||
alert( 'The 2nd rabbit!' );
|
||||
alert( 'The 3rd rabbit!' );
|
||||
</script>
|
||||
*/!*
|
||||
|
||||
<p>Кролики посчитаны!</p>
|
||||
<p>Rabbits counted!</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
```
|
||||
|
||||
Такое поведение называют "синхронным". Как правило, оно вполне нормально, но есть важное следствие.
|
||||
The behavior is called "synchronous". Usually it causes no problems, but there's an important consequence.
|
||||
|
||||
**Если скрипт -- внешний, то пока браузер не выполнит его, он не покажет часть страницы под ним.**
|
||||
**If the script is external, then until the browser executes it, it can't show the page below.**
|
||||
|
||||
То есть, в таком документе, пока не загрузится и не выполнится `big.js`, содержимое `<body>` будет скрыто:
|
||||
So, in this document, until `big.js` loads and executes, the `<body>` content is hidden:
|
||||
|
||||
```html
|
||||
<html>
|
||||
|
@ -108,144 +102,155 @@
|
|||
*/!*
|
||||
</head>
|
||||
<body>
|
||||
Этот текст не будет показан, пока браузер не выполнит big.js.
|
||||
This text is not shown until the browser executes big.js.
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
И здесь вопрос -- действительно ли мы этого хотим? То есть, действительно ли оставшуюся часть страницы нельзя показывать до загрузки скрипта?
|
||||
The question is -- do we really want that?
|
||||
|
||||
Есть ситуации, когда мы не только НЕ хотим такой задержки, но она даже опасна.
|
||||
Most of time, we don't.
|
||||
|
||||
Например, если мы подключаем внешний скрипт, который показывает рекламу или вставляет счётчик посещений, а затем идёт наша страница. Конечно, неправильно, что пока счётчик или реклама не подгрузятся -- оставшаяся часть страницы не показывается. Счётчик посещений не должен никак задерживать отображение страницы сайта. Реклама тоже не должна тормозить сайт и нарушать его функционал.
|
||||
Sometimes, the script contains a very important code that really must be loaded before the rest of the page is parsed (and the scripts below executed). But most of time we'd like to let the visitor see the content while the script is loading.
|
||||
|
||||
А что, если сервер, с которого загружается внешний скрипт, перегружен? Посетитель в этом случае может ждать очень долго!
|
||||
[warn header="Blocking is dangerous"]
|
||||
There are situations when such blocking is even dangerous.
|
||||
|
||||
Вот пример, с подобным скриптом (стоит искусственная задержка загрузки):
|
||||
Let's say we attach a script from the banner system, or a 3rd-party integration code.
|
||||
|
||||
It's just wrong that the rest of the page is not shown until the banner system initialized. The banner is not that important.
|
||||
|
||||
And what if their server is overloaded and responds slowly? Our visitors will wait even more.
|
||||
|
||||
Here's an example of such "slow" script (the delay is artificial here):
|
||||
|
||||
```html
|
||||
<!--+ run height=100 -->
|
||||
<p>Важная информация не покажется, пока не загрузится скрипт.</p>
|
||||
<p>Important information below is not shown until the script loads and executes.</p>
|
||||
|
||||
<script src="https://js.cx/hello/ads.js?speed=0"></script>
|
||||
<script src="https://en.js.cx/hello/ads.js?speed=0"></script>
|
||||
|
||||
<p>...Важная информация!</p>
|
||||
<p>…Important information!</p>
|
||||
```
|
||||
[/warn]
|
||||
|
||||
Что делать?
|
||||
So, how to "fix" the blocking behavior?
|
||||
|
||||
Можно поставить все подобные скрипты в конец страницы -- это уменьшит проблему, но не избавит от неё полностью, если скриптов несколько. Допустим, в конце страницы 3 скрипта, и первый из них тормозит -- получается, другие два его будут ждать -- тоже нехорошо.
|
||||
Our first attempt could be to put all such scripts to the bottom of the `<body>`, after all content. Then the browser will show the content first and then load the script. Problem gone.
|
||||
|
||||
Кроме того, браузер дойдёт до скриптов, расположенных в конце страницы, они начнут грузиться только тогда, когда вся страница загрузится. А это не всегда правильно. Например, счётчик посещений наиболее точно сработает, если загрузить его пораньше.
|
||||
But the solution is not perfect:
|
||||
|
||||
Поэтому "расположить скрипты внизу" -- не лучший выход.
|
||||
<ol>
|
||||
<li>The script won't start loading until the whole page loads. If the page is large, then the delay may be significant. We'd like the browser to start loading a script early.</li>
|
||||
<li>If there is more than one scripts at the bottom of the page, and the first script is slow, then the second one will still has wait for it. Scripts still depend one on another, that's not always welcome. Ads and counter can run independently.</li>
|
||||
</ol>
|
||||
|
||||
And here come the attributes `async` and `defer`.
|
||||
|
||||
Кардинально решить эту проблему помогут атрибуты `async` или `defer`:
|
||||
<dl>
|
||||
<dt>Атрибут `async`</dt>
|
||||
<dd>Поддерживается всеми браузерами, кроме IE9-. Скрипт выполняется полностью асинхронно. То есть, при обнаружении `<script async src="...">` браузер не останавливает обработку страницы, а спокойно работает дальше. Когда скрипт будет загружен -- он выполнится.</dd>
|
||||
<dt>Атрибут `defer`</dt>
|
||||
<dd>Поддерживается всеми браузерами, включая самые старые IE. Скрипт также выполняется асинхронно, не заставляет ждать страницу, но есть два отличия от `async`.
|
||||
<dt>The `async` attribute.</dt>
|
||||
<dd>The script is executed asynchronously. In other words, when the browser meets `<script async src="...">`, it does not stop showing the page. It just initiates script loading and goes on. When the script loads -- it runs.</dd>
|
||||
<dt>The `defer` attribute.</dt>
|
||||
<dd>The script with `defer` also executes asynchronously, like async. But there are two essential differences.
|
||||
|
||||
Первое -- браузер гарантирует, что относительный порядок скриптов с `defer` будет сохранён.
|
||||
First -- the browser guarantees to keep the relative order of scripts with `defer`.
|
||||
|
||||
То есть, в таком коде (с `async`) первым сработает тот скрипт, который раньше загрузится:
|
||||
For example, in the code below (with `async`) there are two scripts. The one which loads first will run first.
|
||||
|
||||
```html
|
||||
<script src="1.js" async></script>
|
||||
<script src="2.js" async></script>
|
||||
```
|
||||
|
||||
А в таком коде (с `defer`) первым сработает всегда `1.js`, а скрипт `2.js`, даже если загрузился раньше, будет его ждать.
|
||||
With `async` it may happen that `2.js` will run before `1.js`. Scripts are totally independent.
|
||||
|
||||
And in the other code `defer` is used, which forces browser to keeps execution order. Even if `2.js` loads first, it will execute after `1.js`:
|
||||
|
||||
```html
|
||||
<script src="1.js" defer></script>
|
||||
<script src="2.js" defer></script>
|
||||
```
|
||||
|
||||
Поэтому атрибут `defer` используют в тех случаях, когда второй скрипт `2.js` зависит от первого `1.js`, к примеру -- использует что-то, описанное первым скриптом.
|
||||
So `defer` is used when the second script `2.js` depends on the first one `1.js`, say uses something described in the first script.
|
||||
|
||||
Второе отличие -- скрипт с `defer` сработает, когда весь HTML-документ будет обработан браузером.
|
||||
The second difference -- script with `defer` always works when the HTML-document is fully processed by the browser.
|
||||
|
||||
For example, when the document is large...
|
||||
|
||||
Например, если документ достаточно большой...
|
||||
```html
|
||||
<script src="async.js" async></script>
|
||||
<script src="defer.js" defer></script>
|
||||
|
||||
Много много много букв
|
||||
Too long text. Didn't read. Many words.
|
||||
```
|
||||
|
||||
...То скрипт `async.js` выполнится, как только загрузится -- возможно, до того, как весь документ готов. А `defer.js` подождёт готовности всего документа.
|
||||
...Then `async.js` executes when it runs -- possibly, before the text is fully loaded. In contrast, `defer.js` always waits for the full document to be ready.
|
||||
|
||||
Это бывает удобно, когда мы в скрипте хотим работать с документом, и должны быть уверены, что он полностью получен.
|
||||
It's great to have the choice here. Sometimes a script doesn't need the document at all (like a counter), then `async` is superb. And if we need the whole document to process it, then `defer` will work nice.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
[smart header="`async` вместе с `defer`"]
|
||||
При одновременном указании `async` и `defer` в современных браузерах будет использован только `async`, в IE9- -- только `defer` (не понимает `async`).
|
||||
[smart header="`async` together with `defer`"]
|
||||
We can't use both `defer` and `async` on a single script. If we do that, `defer` will be ignored.
|
||||
[/smart]
|
||||
|
||||
[warn header="Атрибуты `async/defer` -- только для внешних скриптов"]
|
||||
Атрибуты `async/defer` работают только в том случае, если назначены на внешние скрипты, т.е. имеющие `src`.
|
||||
[warn header="Attributes `async/defer` -- only for external scripts"]
|
||||
Attribute `async/defer` work only when set on a script with `src`.
|
||||
|
||||
При попытке назначить их на обычные скрипты <code><script>...</script></code>, они будут проигнороированы.
|
||||
On a script without `src` like <code><script>...</script></code>, they will be ignored.
|
||||
[/warn]
|
||||
|
||||
Тот же пример с `async`:
|
||||
Let's modify the "blocking script" example that we've seen before, adding `async`:
|
||||
|
||||
```html
|
||||
<!--+ run height=100 -->
|
||||
<p>Важная информация теперь не ждёт, пока загрузится скрипт...</p>
|
||||
<p>Important information below is not shown until the script loads and executes.</p>
|
||||
|
||||
<script *!*async*/!* src="https://js.cx/hello/ads.js?speed=0"></script>
|
||||
<script *!*async*/!* src="https://en.js.cx/hello/ads.js?speed=0"></script>
|
||||
|
||||
<p>...Важная информация!</p>
|
||||
<p>…Important information!</p>
|
||||
```
|
||||
|
||||
При запуске вы увидите, что вся страница отобразилась тут же, а `alert` из внешнего скрипта появится позже, когда загрузится скрипт.
|
||||
Now if we run it, we'll see that the whole document is displayed immediately, and the external script runs when it loads.
|
||||
|
||||
[smart header="Эти атрибуты давно \"в ходу\""]
|
||||
Большинство современных систем рекламы и счётчиков знают про эти атрибуты и используют их.
|
||||
[smart header="Running ahead..."]
|
||||
For an advanced reader who knows that new tags can be added on page dynamically, we'd like to note that the `<script>` tags added in such a way behave as if they have `async`.
|
||||
|
||||
Перед вставкой внешнего тега `<script>` понимающий программист всегда проверит, есть ли у него подобный атрибут. Иначе медленный скрипт может задержать загрузку страницы.
|
||||
[/smart]
|
||||
In other words, they run as they load without an order.
|
||||
|
||||
[smart header="Забегая вперёд"]
|
||||
Для продвинутого читателя, который знает, что теги `<script>` можно добавлять на страницу в любой момент при помощи самого javascript, заметим, что скрипты, добавленные таким образом, ведут себя так же, как `async`. То есть, выполняются как только загрузятся, без сохранения относительного порядка.
|
||||
If we'd like to add several `<script>` tags on the page and keep their execution order, it is possible via `script.async = false`.
|
||||
|
||||
Если же нужно сохранить порядок выполнения, то есть добавить несколько скриптов, которые выполнятся строго один за другим, то используется свойство `script.async = false`.
|
||||
|
||||
|
||||
Выглядит это примерно так:
|
||||
Like this:
|
||||
```js
|
||||
function addScript(src);
|
||||
var script = document.createElement('script');
|
||||
script.src = src;
|
||||
*!*
|
||||
script.async = false; // чтобы гарантировать порядок
|
||||
script.async = false;
|
||||
*/!*
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
|
||||
addScript('1.js'); // загружаться эти скрипты начнут сразу
|
||||
addScript('2.js'); // выполнятся, как только загрузятся
|
||||
addScript('3.js'); // но, гарантированно, в порядке 1 -> 2 -> 3
|
||||
addScript('1.js'); // all these scripts will start loading immediately
|
||||
addScript('2.js'); // but execute in the order of insertion
|
||||
addScript('3.js'); // that is: 1 -> 2 -> 3
|
||||
```
|
||||
|
||||
Более подробно работу со страницей мы разберём во второй части учебника.
|
||||
We'll cover page manipulation in detail later, in the second part of the tutorial.
|
||||
[/smart]
|
||||
|
||||
|
||||
## Итого
|
||||
## Summary
|
||||
|
||||
<ul>
|
||||
<li>Скрипты вставляются на страницу как текст в теге `<script>`, либо как внешний файл через `<script src="путь"></script>`</li>
|
||||
<li>Специальные атрибуты `async` и `defer` используются для того, чтобы пока грузится внешний скрипт -- браузер показал остальную (следующую за ним) часть страницы. Без них этого не происходит.</li>
|
||||
<li>Разница между `async` и `defer`: атрибут `defer` сохраняет относительную последовательность скриптов, а `async` -- нет. Кроме того, `defer` всегда ждёт, пока весь HTML-документ будет готов, а `async` -- нет.</li>
|
||||
<li>Scripts in an external file can be inserted on the page via `<script src="path"></script>`.</li>
|
||||
<li>Normally, the browser doesn't show the document after the script until it executes. Unless the script has `async` or `defer` attributes.</li>
|
||||
<li>Both `async` and `defer` allow the browser to start script loading and then continue to parse/show the page. They both only work on external scripts.</li>
|
||||
<li>The difference is that `defer` keeps the relative script order and always executes after the document is fully loaded. In contrast, `async` script executes when it loads, without any conditions.</li>
|
||||
</ul>
|
||||
|
||||
Очень важно не только читать учебник, но делать что-то самостоятельно.
|
||||
Most modern systems that provide scripts know about these attributes and use them.
|
||||
|
||||
Решите задачки, чтобы удостовериться, что вы всё правильно поняли.
|
||||
Before inserting an external `<script>` tag, one should always check if it should block the page or not. Especially if it's a 3rd-party script. And if not, then `defer/async` can come in handy.
|
||||
|
||||
|
||||
|
|
|
@ -1,45 +1,46 @@
|
|||
# Структура кода
|
||||
# Code structure
|
||||
|
||||
In this section we explore the code structure and statements.
|
||||
|
||||
В этой главе мы рассмотрим общую структуру кода, команды и их разделение.
|
||||
[cut]
|
||||
## Команды
|
||||
## Statements
|
||||
|
||||
Раньше мы уже видели пример команды: `alert('Привет, мир!')` выводит сообщение.
|
||||
We've already seen an example of a statement: `alert('Hello, world!')` shows the message.
|
||||
|
||||
Для того, чтобы добавить в код ещё одну команду -- можно поставить её после точки с запятой.
|
||||
To add one more statement to the code, it can be separated with a semicolon.
|
||||
|
||||
Например, вместо одного вызова `alert` сделаем два:
|
||||
Let's make split the message into two messages:
|
||||
|
||||
```js
|
||||
//+ run no-beautify
|
||||
alert('Привет'); alert('Мир');
|
||||
alert('Hello'); alert('World');
|
||||
```
|
||||
|
||||
Как правило, каждая команда пишется на отдельной строке -- так код лучше читается:
|
||||
Usually each statement is written on a separate line -- thus the code becomes more readable:
|
||||
|
||||
```js
|
||||
//+ run no-beautify
|
||||
alert('Привет');
|
||||
alert('Мир');
|
||||
alert( 'Hello' );
|
||||
alert( 'World' );
|
||||
```
|
||||
|
||||
## Точка с запятой [#semicolon]
|
||||
## The semicolon [#semicolon]
|
||||
|
||||
Точку с запятой *во многих случаях* можно не ставить, если есть переход на новую строку.
|
||||
The semicolon may be omitted in most cases when a line break exists.
|
||||
|
||||
Так тоже будет работать:
|
||||
This would also work:
|
||||
|
||||
```js
|
||||
//+ run no-beautify
|
||||
alert('Привет')
|
||||
alert('Мир')
|
||||
alert( 'Hello' )
|
||||
alert( 'World' )
|
||||
```
|
||||
|
||||
В этом случае JavaScript интерпретирует переход на новую строчку как разделитель команд и автоматически вставляет "виртуальную" точку с запятой между ними.
|
||||
In this case JavaScript interprets the line break as a splitter and automatically assumes a "virtual" semicolon between them.
|
||||
|
||||
**Однако, важно то, что "во многих случаях" не означает "всегда"!**
|
||||
**But it's important that "in most cases" does not mean "always"!**
|
||||
|
||||
Например, запустите этот код:
|
||||
Consider this code as an example:
|
||||
|
||||
```js
|
||||
//+ run no-beautify
|
||||
|
@ -48,99 +49,103 @@ alert(3 +
|
|||
+ 2);
|
||||
```
|
||||
|
||||
Выведет 6.
|
||||
It outputs `6`.
|
||||
|
||||
То есть, точка с запятой не ставится. Почему? Интуитивно понятно, что здесь дело в "незавершённом выражении", конца которого JavaScript ждёт с первой строки и поэтому не ставит точку с запятой. И здесь это, пожалуй, хорошо и приятно.
|
||||
JavaScript does not insert semicolons here. It is intuitively obvious that the reason is the "uncomplete expression". JavaScript notes that the line ends with a plus `+` and awaits the expression to continue on the next line. And that is actually fine and comfortable here.
|
||||
|
||||
**Но в некоторых важных ситуациях JavaScript "забывает" вставить точку с запятой там, где она нужна.**
|
||||
**But there are situations where "fails" to assume a semicolon where it is really needed.**
|
||||
|
||||
Таких ситуаций не так много, но ошибки, которые при этом появляются, достаточно сложно обнаруживать и исправлять.
|
||||
Errors which come appear in such cases are quite hard to find and fix.
|
||||
|
||||
Чтобы не быть голословным, вот небольшой пример.
|
||||
[smart header="An example of the error"]
|
||||
For a curious reader who might be interested in a concrete example, check this code out:
|
||||
|
||||
Такой код работает:
|
||||
```js
|
||||
//+ run
|
||||
[1, 2].forEach(alert)
|
||||
```
|
||||
|
||||
Он выводит по очереди `1`, `2`. Почему он работает -- сейчас не важно, позже разберёмся.
|
||||
It shows `1` then `2`. How it works -- does not matter now, we'll get deal with it later.
|
||||
|
||||
Важно, что вот такой код уже работать не будет:
|
||||
But let's insert an `alert` without a semicolon before it:
|
||||
|
||||
```js
|
||||
//+ run no-beautify
|
||||
alert("Сейчас будет ошибка")
|
||||
alert( "Without a semicolon we get an error here" )
|
||||
[1, 2].forEach(alert)
|
||||
```
|
||||
|
||||
Выведется только первый `alert`, а дальше -- ошибка. Потому что перед квадратной скобкой JavaScript точку с запятой не ставит, а как раз здесь она нужна (упс!).
|
||||
Now only the first `alert` is shown, not the numbers. And we can see an error in the browser console. That's actually because JavaScript does not insert a semicolon before square brackets `[...]` and misinterprets the code.
|
||||
|
||||
Если её поставить, то всё будет в порядке:
|
||||
Everything's fine if we add a semicolon:
|
||||
```js
|
||||
//+ run
|
||||
alert( "Сейчас будет ошибка" );
|
||||
alert( "With the semicolon everything works" );
|
||||
[1, 2].forEach(alert)
|
||||
```
|
||||
|
||||
**Поэтому в JavaScript рекомендуется точки с запятой ставить. Сейчас это, фактически, стандарт, которому следуют все большие проекты.**
|
||||
|
||||
## Комментарии
|
||||
|
||||
Со временем программа становится большой и сложной. Появляется необходимость добавить *комментарии*, которые объясняют, что происходит и почему.
|
||||
|
||||
Комментарии могут находиться в любом месте программы и никак не влияют на её выполнение. Интерпретатор JavaScript попросту игнорирует их.
|
||||
|
||||
*Однострочные комментарии* начинаются с двойного слэша `//`. Текст считается комментарием до конца строки:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
// Команда ниже говорит "Привет"
|
||||
alert( 'Привет' );
|
||||
|
||||
alert( 'Мир' ); // Второе сообщение выводим отдельно
|
||||
```
|
||||
|
||||
*Многострочные комментарии* начинаются слешем-звездочкой <code>"/*"</code> и заканчиваются звездочкой-слэшем <code>"*/"</code>, вот так:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
/* Пример с двумя сообщениями.
|
||||
Это - многострочный комментарий.
|
||||
*/
|
||||
alert( 'Привет' );
|
||||
alert( 'Мир' );
|
||||
```
|
||||
|
||||
Всё содержимое комментария игнорируется. Если поместить код внутрь <code>/* ... */</code> или после `//` -- он не выполнится.
|
||||
|
||||
```js
|
||||
//+ run
|
||||
/* Закомментировали код
|
||||
alert( 'Привет' );
|
||||
*/
|
||||
alert( 'Мир' );
|
||||
```
|
||||
|
||||
[smart header="Используйте горячие клавиши!"]
|
||||
В большинстве редакторов комментарий можно поставить горячей клавишей, обычно это [key Ctrl+/] для однострочных и что-то вроде [key Ctrl+Shift+/] -- для многострочных комментариев (нужно выделить блок и нажать сочетание клавиш). Детали смотрите в руководстве по редактору.
|
||||
[/smart]
|
||||
|
||||
[warn header="Вложенные комментарии не поддерживаются!"]
|
||||
В этом коде будет ошибка:
|
||||
As a conclusion, it's recommended to put semicolons between statements even if they are separated by newlines. This rule is widely adopted by the community.
|
||||
|
||||
## Comments
|
||||
|
||||
As the time goes, the program becomes more and more complex. It becomes necessary to add *comments* which describe what happens and why.
|
||||
|
||||
Comments can be put into any place of the script. They don't affect it's execution. The JavaScript interpreter simply ignores them.
|
||||
|
||||
*One-line comments* start with a double slash `//`. The text after them till the end of line is considered a comment.
|
||||
|
||||
It may occupy a full line of it's own or follow a statement, like this:
|
||||
```js
|
||||
//+ run
|
||||
// The statement below outputs a word "Hello"
|
||||
alert( 'Hello' );
|
||||
|
||||
alert( 'World' ); // ...The second word is shown separately.
|
||||
```
|
||||
|
||||
*Multiline comments* start with a slash and a star <code>"/*"</code> and end with a star and a slash <code>"*/"</code>, like this:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
/* An example with two messages.
|
||||
This is a multiline comment.
|
||||
*/
|
||||
alert( 'Hello' );
|
||||
alert( 'World' );
|
||||
```
|
||||
|
||||
All contents of comments is ignored. If we put a code inside <code>/* ... */</code> or after `//` it won't execute.
|
||||
|
||||
```js
|
||||
//+ run
|
||||
/* Commenting out the code
|
||||
alert( 'Привет' );
|
||||
*/
|
||||
alert( 'Мир' );
|
||||
```
|
||||
|
||||
[smart header="Use hotkeys!"]
|
||||
In most editors a line of code can be commented out by [key Ctrl+/] hotkey for a single-line comment and something like [key Ctrl+Shift+/] -- for multiline comments (select a code and press the hotkey).
|
||||
[/smart]
|
||||
|
||||
[warn header="Nested comments are not supported!"]
|
||||
There may not be comments inside comments.
|
||||
|
||||
This code will die with an error:
|
||||
|
||||
```js
|
||||
//+ run no-beautify
|
||||
/*
|
||||
/* вложенный комментарий ?!? */
|
||||
/* nested comment ?!? */
|
||||
*/
|
||||
alert('Мир');
|
||||
alert( 'World' );
|
||||
```
|
||||
|
||||
[/warn]
|
||||
|
||||
Don't hesitate to comment. They more code is in the project -- the more helpful good comments are.
|
||||
|
||||
Не бойтесь комментариев. Чем больше кода в проекте -- тем они важнее. Что же касается увеличения размера кода -- это не страшно, т.к. существуют инструменты сжатия JavaScript, которые при публикации кода легко их удалят.
|
||||
Comments increase the overall code footprint, but that's not a problem at all, because there are many tools which minify the code before publishing to production server and remove comments in the process.
|
||||
|
||||
На следующих занятиях мы поговорим о переменных, блоках и других структурных элементах программы на JavaScript.
|
||||
In our next sections we'll talk about other structure elements of JavaScript like blocks, variables and more.
|
||||
|
||||
|
|
|
@ -1,80 +1,55 @@
|
|||
# Современный стандарт, "use strict"
|
||||
# The modern mode, "use strict"
|
||||
|
||||
Очень долго язык JavaScript развивался без потери совместимости. Новые возможности добавлялись в язык, но старые -- никогда не менялись, чтобы не "сломать" уже существующие HTML/JS-страницы с их использованием.
|
||||
For a long time JavaScript was evolving without compatibility issues. New features got added to the language, but the old ones did not change.
|
||||
|
||||
Однако, это привело к тому, что любая ошибка в дизайне языка становилась "вмороженной" в него навсегда.
|
||||
That had the benefit of never breaking the existing code. But the back side is that any mistake or imprefect decision made by JavaScript creators got stuck in the language forever.
|
||||
|
||||
Так было до появления стандарта EcmaScript 5 (ES5), который одновременно добавил новые возможности и внёс в язык ряд исправлений, которые могут привести к тому, что старый код, который был написан до его появления, перестанет работать.
|
||||
It had been so before EcmaScript 5 (ES5) appeared with added new features to the language and modified some of the existing ones.
|
||||
|
||||
Чтобы этого не случилось, решили, что по умолчанию эти опасные изменения будут выключены, и код будет работать по-старому. А для того, чтобы перевести код в режим полного соответствия современному стандарту, нужно указать специальную директиву `use strict`.
|
||||
|
||||
Эта директива не поддерживается IE9-.
|
||||
To keep old code working, by default most modifications of the pre-existing features are off. We need to enable them manually with a special directive `use strict`.
|
||||
|
||||
[cut]
|
||||
|
||||
## Директива use strict
|
||||
## "use strict"
|
||||
|
||||
Директива выглядит как строка `"use strict";` или `'use strict';` и ставится в начале скрипта.
|
||||
The directive looks like a string `"use strict";` or `'use strict';`. When it is located on the top of the script, then the whole script works the "modern" way.
|
||||
|
||||
Например:
|
||||
For example
|
||||
|
||||
```js
|
||||
"use strict";
|
||||
|
||||
// этот код будет работать по современному стандарту ES5
|
||||
// this code works the modern way
|
||||
...
|
||||
```
|
||||
|
||||
[warn header="Отменить действие `use strict` никак нельзя"]
|
||||
Не существует директивы `no use strict` или подобной, которая возвращает в старый режим.
|
||||
[warn header="There's no way to cancel `use strict`"]
|
||||
There is no directive `"no use strict"` or alike, that would return the old behavior.
|
||||
|
||||
Если уж вошли в современный режим, то это дорога в один конец.
|
||||
Once we enter the strict mode, there's no return.
|
||||
[/warn]
|
||||
|
||||
[smart header="`use strict` для функций"]
|
||||
Через некоторое время мы будем проходить [функции](/function-basics). На будущее заметим, что `use strict` также можно указывать в начале функций, тогда строгий режим будет действовать только внутри функции.
|
||||
[smart header="`use strict` for functions"]
|
||||
We will learn [functions](/function-basics) very soon. For the future let's note that `use strict` can be put at the start of a function instead of the whole script. Then the strict mode is enabled in this function only.
|
||||
[/smart]
|
||||
|
||||
В следующих главах мы будем подробно останавливаться на отличиях в работе языка при `use strict` и без него.
|
||||
## Do I really need "use strict"?
|
||||
|
||||
## Нужен ли мне "use strict"?
|
||||
Actually, yes. All modern browsers support it.
|
||||
|
||||
Если говорить абстрактно, то -- да, нужен. В строгом режиме исправлены некоторые ошибки в дизайне языка, и вообще, современный стандарт -- это хорошо.
|
||||
More than that, there are several JavaScript features that enable strict mode implicitly, "by default". So if we use for example [classes](/classes) (covered later), they implicitly switch the interpreter to "strict mode".
|
||||
|
||||
Однако, есть и две проблемы.
|
||||
So there's no way to stay modern and evade `"use strict"`. Let's put it everywhere.
|
||||
|
||||
<dl>
|
||||
<dt>Поддержка браузеров IE9-, которые игнорируют `"use strict"`.</dt>
|
||||
<dd>Предположим, что мы, используя `"use strict"`, разработали код и протестировали его в браузере Chrome. Всё работает... Однако, вероятность ошибок при этом в IE9- выросла! Он-то всегда работает по старому стандарту, а значит, иногда по-другому. Возникающие ошибки придётся отлаживать уже в IE9-, и это намного менее приятно, нежели в Chrome.
|
||||
The only downside is Internet Explorer prior to version 10. Those browsers do not support `use strict`, so we need to make sure that our code is compatible with the old behavior. That won't cause any problems for us.
|
||||
|
||||
Впрочем, проблема не так страшна. Несовместимостей мало. И если их знать (а в учебнике мы будем останавливаться на них) и писать правильный код, то всё будет в порядке и `"use strict"` станет нашим верным помощником.
|
||||
</dd>
|
||||
<dt>Библиотеки, написанные без учёта `"use strict"`.</dt>
|
||||
<dd>Некоторые библиотеки, которые написаны без `"use strict"`, не всегда корректно работают, если вызывающий код содержит `"use strict"`.
|
||||
Another minor problem is the 3rd party libraries, few of them are written without `use strict` in mind and do not work correctly when the calling code is in the strict mode. But that happens very rarely.
|
||||
|
||||
В первую очередь имеются в виду сторонние библиотеки, которые писали не мы, и которые не хотелось бы переписывать или править.
|
||||
All code in the tutorial works correctly in `use strict`.
|
||||
|
||||
Таких библиотек мало, но при переводе давно существующих проектов на `"use strict"` эта проблема возникает с завидной регулярностью.
|
||||
</dd>
|
||||
</dl>
|
||||
## Summary
|
||||
|
||||
Вывод?
|
||||
Here we got acquanted with the notion of a "strict mode".
|
||||
|
||||
**Писать код с `use strict` следует лишь в том случае, если вы уверены, что описанных выше проблем не будет.**
|
||||
|
||||
Конечно же, весь код, который находится в этом учебнике, корректно работает в режиме `"use strict"`.
|
||||
|
||||
## ES5-shim [#es5-shim]
|
||||
|
||||
Браузер IE8 поддерживает только совсем старую версию стандарта JavaScript, а именно ES3.
|
||||
|
||||
К счастью, многие возможности современного стандарта можно добавить в этот браузер, подключив библиотеку [ES5 shim](https://github.com/es-shims/es5-shim), а именно -- скрипты `es5-shim.js` и `es5-sham.js` из неё.
|
||||
|
||||
## Итого
|
||||
|
||||
В этой главе мы познакомились с понятием "строгий режим".
|
||||
|
||||
Далее мы будем предполагать, что разработка ведётся либо в современном браузере, либо в IE8- с подключённым [ES5 shim](https://github.com/es-shims/es5-shim). Это позволит нам использовать большинство возможностей современного JavaScript во всех браузерах.
|
||||
|
||||
Очень скоро, буквально в следующей главе, мы увидим особенности строгого режима на конкретных примерах.
|
||||
It is strongly advised to use it everywhere. Very soon, in the next chapter we'll see the differences of the strict mode in examples.
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
Каждая строчка решения соответствует одному шагу задачи:
|
||||
In the code below, each line corresponds to the item in the task list.
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var admin, name; // две переменных через запятую
|
||||
var admin, name; // can declare two variables at once
|
||||
|
||||
name = "Василий";
|
||||
name = "John";
|
||||
|
||||
admin = name;
|
||||
|
||||
alert( admin ); // "Василий"
|
||||
alert( admin ); // "John"
|
||||
```
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
# Работа с переменными
|
||||
# Working with variables
|
||||
|
||||
[importance 2]
|
||||
|
||||
<ol>
|
||||
<li>Объявите две переменные: `admin` и `name`. </li>
|
||||
<li>Запишите в `name` строку `"Василий"`. </li>
|
||||
<li>Скопируйте значение из `name` в `admin`.</li>
|
||||
<li>Выведите `admin` (должно вывести "Василий").</li>
|
||||
<li>Declare two variables: `admin` and `name`. </li>
|
||||
<li>Assign the value `"John"` to `name`.</li>
|
||||
<li>Copy the value from `name` to `admin`.</li>
|
||||
<li>Show the value of `admin` using `alert` (must output "John").</li>
|
||||
</ol>
|
|
@ -0,0 +1,21 @@
|
|||
First, the variable for the name of our planet.
|
||||
|
||||
That's simple:
|
||||
|
||||
```js
|
||||
var 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.
|
||||
|
||||
Second, the name of the current visitor:
|
||||
|
||||
```js
|
||||
var currentUserName = "John";
|
||||
```
|
||||
|
||||
Again, we could shorten that to `userName` if we know beyound the reasonable doubt that the user is current.
|
||||
|
||||
Modern editors and autocomplete make long variable names easy to write. Don't save on them. Say, a name with 3 words in it is fine.
|
||||
|
||||
And if your editor does not help here, get [a new one](/editor).
|
|
@ -0,0 +1,8 @@
|
|||
# Giving the right name
|
||||
|
||||
[importance 3]
|
||||
|
||||
<ol>
|
||||
<li>Create the variable to store the name of our planet. Assign the value `"Earth"` to it. What should be its name?</li>
|
||||
<li>Create the variable to store the name of the current visitor. What about its name?</li>
|
||||
</ol>
|
|
@ -1,60 +1,84 @@
|
|||
# Переменные
|
||||
# Variables
|
||||
|
||||
В зависимости от того, для чего вы делаете скрипт, понадобится работать с информацией.
|
||||
Depending on our aims, the script needs to work with the information.
|
||||
|
||||
Если это электронный магазин -- то это товары, корзина. Если чат -- посетители, сообщения и так далее.
|
||||
If it's an online-shop -- that's going to be the goods and the card. If it's a chat -- visitors, message and so on.
|
||||
|
||||
Variables are used to store the information.
|
||||
|
||||
Чтобы хранить информацию, используются *переменные*.
|
||||
[cut]
|
||||
## Переменная
|
||||
|
||||
*Переменная* состоит из имени и выделенной области памяти, которая ему соответствует.
|
||||
## A variable
|
||||
|
||||
Для *объявления* или, другими словами, *создания переменной* используется ключевое слово `var`:
|
||||
According to Wikipedia, a [variable]("https://en.wikipedia.org/wiki/Variable_(computer_science)") is a storage location paired with an associated symbolic name (identifier). The name is used to access the stored information.
|
||||
|
||||
To declare a variable in JavaScript, there are two keywords:
|
||||
|
||||
<ol>
|
||||
<li>the `var` keyword comes from the ancient times.</li>
|
||||
<li>the `let` keyword is a "modern school".</li>
|
||||
</ol>
|
||||
|
||||
We'll start with `var`, because it is widely used in older scripts and we need to understand it. Later when we know enough to understand the subtle differences (when they actually matter for us) we'll move further to `let`.
|
||||
|
||||
The statement below creates (in other words: *declares* or *defines*) the variable `message`:
|
||||
|
||||
```js
|
||||
var message;
|
||||
```
|
||||
|
||||
После объявления, можно записать в переменную данные:
|
||||
Now we can assign some data into it:
|
||||
|
||||
```js
|
||||
var message;
|
||||
message = 'Hello'; // сохраним в переменной строку
|
||||
message = 'Hello'; // keep the string
|
||||
```
|
||||
|
||||
Эти данные будут сохранены в соответствующей области памяти и в дальнейшем доступны при обращении по имени:
|
||||
The string is now saved into the associated memory area. We can access it using the variable name:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var message;
|
||||
message = 'Hello!';
|
||||
|
||||
alert( message ); // выведет содержимое переменной
|
||||
alert( message ); // shows the variable content
|
||||
```
|
||||
|
||||
Для краткости можно совместить объявление переменной и запись данных:
|
||||
To be concise we can merge the variable declaration and assignment into a single line:
|
||||
|
||||
```js
|
||||
var message = 'Hello!';
|
||||
```
|
||||
|
||||
Можно даже объявить несколько переменных сразу:
|
||||
We can also declare multiple variables in one line:
|
||||
|
||||
```js
|
||||
//+ no-beautify
|
||||
var user = 'John', age = 25, message = 'Hello';
|
||||
```
|
||||
|
||||
### Аналогия из жизни
|
||||
That might seem shorter, but it's recommended, for the sake of beter readability, to use a single line per variable.
|
||||
|
||||
Проще всего понять переменную, если представить её как "коробку" для данных, с уникальным именем.
|
||||
This code is a bit longer, but easier to read:
|
||||
|
||||
Например, переменная `message` -- это коробка, в которой хранится значение `"Hello!"`:
|
||||
```js
|
||||
//+ no-beautify
|
||||
var user = 'John';
|
||||
var age = 25;
|
||||
var message = 'Hello';
|
||||
```
|
||||
|
||||
## Real-life analogy
|
||||
|
||||
We can easily grasp the concept of a "variable" if we imagine it as a "box" for the data, with the unique-named sticker on it.
|
||||
|
||||
For instance, the variable `message` -- is a box with the value `"Hello!" labelled `"message"`:
|
||||
|
||||
<img src="variable.png">
|
||||
|
||||
В коробку можно положить любое значение, а позже - поменять его. Значение в переменной можно изменять сколько угодно раз:
|
||||
We can put any value into the box. And later -- we can change it.
|
||||
|
||||
The value can be changed as many times as we need:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
|
@ -62,16 +86,16 @@ var message;
|
|||
|
||||
message = 'Hello!';
|
||||
|
||||
message = 'World!'; // заменили значение
|
||||
message = 'World!'; // value changed
|
||||
|
||||
alert( message );
|
||||
```
|
||||
|
||||
При изменении значения старое содержимое переменной удаляется.
|
||||
When the value is changed, the old data is removed from the variable:
|
||||
|
||||
<img src="variable-change.png">
|
||||
|
||||
Можно объявить две переменные и копировать данные из одной в другую:
|
||||
We can also declare two variables and copy data from one into another.
|
||||
|
||||
```js
|
||||
//+ run
|
||||
|
@ -80,7 +104,7 @@ var hello = 'Hello world!';
|
|||
var message;
|
||||
|
||||
*!*
|
||||
// скопировали значение
|
||||
// copy value
|
||||
message = hello;
|
||||
*/!*
|
||||
|
||||
|
@ -89,90 +113,99 @@ alert( message ); // Hello world!
|
|||
```
|
||||
|
||||
[smart]
|
||||
Существуют [функциональные](http://ru.wikipedia.org/wiki/%D0%AF%D0%B7%D1%8B%D0%BA_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F) языки программирования, в которых значение переменной менять нельзя. Например, [Scala](http://www.scala-lang.org/) или [Erlang](http://www.erlang.org/).
|
||||
It may seem that the ability to change a value is natural, but it's really not so.
|
||||
|
||||
В таких языках положил один раз значение в коробку -- и оно хранится там вечно, ни удалить ни изменить. А нужно что-то другое сохранить -- изволь создать новую коробку (объявить новую переменную), повторное использование невозможно.
|
||||
There also exist [functional](http://ru.wikipedia.org/wiki/%D0%AF%D0%B7%D1%8B%D0%BA_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F) programming languages that forbid to change a variable once it's assigned. For example, [Scala](http://www.scala-lang.org/) and [Erlang](http://www.erlang.org/).
|
||||
|
||||
С виду -- не очень удобно, но, как ни странно, и на таких языках вполне можно успешно программировать. Более того, оказывается, что в ряде областей, например в распараллеливании вычислений, они имеют преимущества. Изучение какого-нибудь функционального языка рекомендуется для расширения кругозора.
|
||||
In such languages, once the value is in the box -- it's there forever. If we need to store something else -- please create a new box (declare a new variable), can't reuse the old one.
|
||||
|
||||
Though it may seem a little bit odd at the first sight, these languages are quite capable of serious development. More than that, there are areas like parallel computations where this limitation infers certain benefits. Studying of such a language (even if not planning to use soon) is recommended to broaden the mind.
|
||||
[/smart]
|
||||
|
||||
## Имена переменных [#variable-naming]
|
||||
## Variable naming [#variable-naming]
|
||||
|
||||
There are two limitations on the variable name in JavaScript:
|
||||
|
||||
На имя переменной в JavaScript наложены всего два ограничения.
|
||||
<ol>
|
||||
<li>Имя может состоять из: букв, цифр, символов `$` и `_`</li>
|
||||
<li>Первый символ не должен быть цифрой.</li>
|
||||
<li>The name must contain only letters, digits, symbols `$` and `_`.</li>
|
||||
<li>The first character must not be a digit.</li>
|
||||
</ol>
|
||||
|
||||
Например:
|
||||
Valid name examples:
|
||||
|
||||
```js
|
||||
var myName;
|
||||
var userName;
|
||||
var test123;
|
||||
```
|
||||
|
||||
**Что особенно интересно -- доллар `'$'` и знак подчеркивания `'_'` являются такими же обычными символами, как буквы:**
|
||||
When the name contains multiple words, [camelCase](https://en.wikipedia.org/wiki/CamelCase) is commonly used. That is: words go one after another with the capital letter at start: `myVeryLongName`.
|
||||
|
||||
What's interesting -- the dollar sign `'$'` and the underscore `'_'` are considered ordinary symbols, just like letters.
|
||||
|
||||
These names are valid:
|
||||
|
||||
```js
|
||||
//+ run untrusted
|
||||
var $ = 1; // объявили переменную с именем '$'
|
||||
var _ = 2; // переменная с именем '_'
|
||||
var $ = 1; // declared a variable with the name "$"
|
||||
var _ = 2; // and now the variable with the name "_"
|
||||
|
||||
alert( $ + _ ); // 3
|
||||
```
|
||||
|
||||
А такие переменные были бы неправильными:
|
||||
Examples of incorrect variable names:
|
||||
|
||||
```js
|
||||
//+ no-beautify
|
||||
var 1a; // начало не может быть цифрой
|
||||
var 1a; // cannot start with a digit
|
||||
|
||||
var my-name; // дефис '-' не является разрешенным символом
|
||||
var my-name; // a hyphen '-' is not allowed in the name
|
||||
```
|
||||
|
||||
[smart header="Регистр букв имеет значение"]
|
||||
Переменные `apple` и `AppLE` -- две разные переменные.
|
||||
[smart header="Case matters"]
|
||||
Variables named `apple` and `AppLE` -- are two different variables.
|
||||
[/smart]
|
||||
|
||||
[smart header="Русские буквы допустимы, но не рекомендуются"]
|
||||
[smart header="Non-english letters are allowed, but not recommended."]
|
||||
|
||||
В названии переменных можно использовать и русские буквы, например:
|
||||
It is possible to use cyrillic letters or even hieroglyphs, like this:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var имя = "Вася";
|
||||
alert( имя ); // "Вася"
|
||||
var имя = 123;
|
||||
var 我 = 456;
|
||||
```
|
||||
|
||||
Технически, ошибки здесь нет, но на практике сложилась традиция использовать в именах только английские буквы.
|
||||
Technically, there is no error here, but there is a tradition to use only latin alphabet in variable names.
|
||||
[/smart]
|
||||
|
||||
[warn header="Зарезервированные имена"]
|
||||
[warn header="Reserved names"]
|
||||
There is a list of reserved words, which cannot be used as variable names, because they are used by the language itself.
|
||||
|
||||
Существует список зарезервированных слов, которые нельзя использовать для переменных, так как они используются самим языком, например: `var, class, return, export` и др.
|
||||
For example: `var, class, return, function` and alike are reserved.
|
||||
|
||||
Например, такой пример выдаст синтаксическую ошибку:
|
||||
The code below will give a syntax error:
|
||||
|
||||
```js
|
||||
//+ run no-beautify
|
||||
var return = 5; // ошибка
|
||||
alert(return);
|
||||
var return = 5; // error!
|
||||
```
|
||||
|
||||
[/warn]
|
||||
|
||||
|
||||
## Важность директивы var
|
||||
## Strict mode and "var"
|
||||
|
||||
В старом стандарте JavaScript разрешалось создавать переменную и без `var`, просто присвоив ей значение:
|
||||
Without strict mode, it is possible to create a variable without a `var`, by a mere assignment of the value:
|
||||
|
||||
```js
|
||||
num = 5; // переменная num будет создана, если ее не было
|
||||
//+ run
|
||||
num = 5; // the variable "num" is created if didn't exist
|
||||
|
||||
alert(num);
|
||||
```
|
||||
|
||||
В режиме `"use strict"` так делать уже нельзя.
|
||||
...But in `"use strict"` it is not allowed.
|
||||
|
||||
Следующий код выдаст ошибку:
|
||||
The code below will give an error:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
|
@ -183,77 +216,108 @@ num = 5; // error: num is not defined
|
|||
*/!*
|
||||
```
|
||||
|
||||
Обратим внимание, директиву `use strict` нужно ставить до кода, иначе она не сработает:
|
||||
[smart header="Ensure that 'use strict' is at the top"]
|
||||
Please make sure that `"use strict"` is on the top of the script, otherwise the strict mode may not be enabled.
|
||||
|
||||
There is no strict mode here:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var something;
|
||||
|
||||
"use strict"; // слишком поздно
|
||||
"use strict"; // too late
|
||||
|
||||
*!*
|
||||
num = 5; // ошибки не будет, так как строгий режим не активирован
|
||||
num = 5; // no error, strict mode is not activated
|
||||
*/!*
|
||||
```
|
||||
[/smart]
|
||||
|
||||
[warn header="Ошибка в IE8- без `var`"]
|
||||
Если же вы собираетесь поддерживать IE8-, то у меня для вас ещё одна причина всегда использовать `var`.
|
||||
## Constants
|
||||
|
||||
Следущий документ в IE8- ничего не выведет, будет ошибка:
|
||||
Variables with a fixed value are called "constant variables" or just *constants*.
|
||||
|
||||
```html
|
||||
<div id="test"></div>
|
||||
<script>
|
||||
*!*
|
||||
test = 5; // здесь будет ошибка!
|
||||
*/!*
|
||||
alert( test ); // не сработает
|
||||
</script>
|
||||
```
|
||||
|
||||
Это потому, что переменная `test` не объявлена через `var` и совпадает с `id` элемента `<div>`. Даже не спрашивайте почему -- это ошибка в браузере IE до версии 9.
|
||||
|
||||
Самое "забавное" то, что такая ошибка присвоения значений будет только в IE8- и только если на странице присутствует элемент с совпадающим с именем `id`.
|
||||
|
||||
Такие ошибки особенно "весело" исправлять и отлаживать.
|
||||
|
||||
Вывод простой -- всегда объявляем переменные через `var`, и сюрпризов не будет. Даже в старых IE.
|
||||
[/warn]
|
||||
|
||||
## Константы
|
||||
|
||||
*Константа* -- это переменная, которая никогда не меняется. Как правило, их называют большими буквами, через подчёркивание. Например:
|
||||
To declare a constant variable, one can use `const`:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var COLOR_RED = "#F00";
|
||||
var COLOR_GREEN = "#0F0";
|
||||
var COLOR_BLUE = "#00F";
|
||||
var COLOR_ORANGE = "#FF7F00";
|
||||
'use strict';
|
||||
|
||||
const myBirthday = '18.04.1982';
|
||||
|
||||
color = '01.01.2001'; // error!
|
||||
```
|
||||
|
||||
The code below can now calculate other values based on the constant, like the age or the sign of the zodiac. It can be sure that the calculations are always valid, because `myBirthday` never changes.
|
||||
|
||||
Please note that `const` variables actually *can be assigned*, but only once.
|
||||
|
||||
This is not an error:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
'use strict';
|
||||
|
||||
const myBirthday;
|
||||
|
||||
myBirthday = '18.04.1982'; // the first assignment
|
||||
```
|
||||
|
||||
|
||||
[smart header="CONSTANT_NAMING"]
|
||||
There is a widespread practice to use constants as aliases for difficult-to-remember values. Such constants are named using capitals and underscores.
|
||||
|
||||
Like this:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
const COLOR_RED = "#F00";
|
||||
const COLOR_GREEN = "#0F0";
|
||||
const COLOR_BLUE = "#00F";
|
||||
const COLOR_ORANGE = "#FF7F00";
|
||||
|
||||
const a;
|
||||
a = 5;
|
||||
|
||||
var color = COLOR_ORANGE;
|
||||
alert( color ); // #FF7F00
|
||||
```
|
||||
|
||||
Технически, константа является обычной переменной, то есть её *можно* изменить. Но мы *договариваемся* этого не делать.
|
||||
`COLOR_ORANGE` is easy to understand and remember. It is much easier to grasp what `color = COLOR_ORANGE` means than `color = "#FF7F00"`.
|
||||
|
||||
Зачем нужны константы? Почему бы просто не писать `var color = "#FF7F00"`?
|
||||
Besides, it is much easier to make a typo in `"#FF7F00"` than in `COLOR_ORANGE`.
|
||||
|
||||
<ol>
|
||||
<li>Во-первых, константа `COLOR_ORANGE` -- это понятное имя. По присвоению `var color="#FF7F00"` непонятно, что цвет -- оранжевый. Иными словами, константа `COLOR_ORANGE` является "понятным псевдонимом" для значения `#FF7F00`.</li>
|
||||
<li>Во-вторых, опечатка в строке, особенно такой сложной как `#FF7F00`, может быть не замечена, а в имени константы её допустить куда сложнее.</li>
|
||||
</ol>
|
||||
So, sometimes constants are used as aliases to complex values, to evade errors and make the code more readable.
|
||||
[/smart]
|
||||
|
||||
**Константы используют вместо строк и цифр, чтобы сделать программу понятнее и избежать ошибок.**
|
||||
|
||||
## Итого
|
||||
## Summary
|
||||
|
||||
<ul>
|
||||
<li>В JavaScript можно объявлять переменные для хранения данных. Это делается при помощи `var`.</li>
|
||||
<li>Технически, можно просто записать значение и без объявления переменной, однако по ряду причин это не рекомендуется.</li>
|
||||
<li>Вместе с объявлением можно сразу присвоить значение: `var x = 10`.</li>
|
||||
<li>Переменные, которые названы `БОЛЬШИМИ_БУКВАМИ`, являются константами, то есть никогда не меняются. Как правило, они используются для удобства, чтобы было меньше ошибок.</li>
|
||||
<li>We must declare variables to store data. That can be done using `var` or `let`. As of now we can think that `let` is a newer alias of `var`, later we'll cover their differences in detail.</li>
|
||||
<li>We can assign a value when the variable is declared: `var x = 10`.</li>
|
||||
<li>If a variable is not going to change after assignment, it is called "a constant". We can use `const` keyword instead of `var` to declare constants.</li>
|
||||
</ul>
|
||||
|
||||
And there's one more thing. The most important one.
|
||||
|
||||
Please name the variables sensibly.
|
||||
|
||||
Variable naming is one of the most important and complex skills in programming. Just looking at variable names can obviously show which code is written by a beginner and which by an experienced guru.
|
||||
|
||||
In the real project, most of time is spent not on writing of the completely new code, but rather on modifying and improving the existing one.
|
||||
|
||||
It might be not so obvious to the one who didn't write big things. Or to a freelances who writes a "read-only code" (write 5 lines, give to the customer, forget). But for the serious and especially team projects, that's always true.
|
||||
|
||||
It is much easier to find the information if it's well-labelled. Or, in other words, when the variables is named right.
|
||||
|
||||
Please spend some time thinking about the right name for a variable before declaring it. That will repay you a lot.
|
||||
|
||||
[warn header="The name must always correspond to the data"]
|
||||
There exist lazy programmers who instead of declaring a new variable, tend to reuse the existing one, write other data into it.
|
||||
|
||||
As the result, the variable is like a box where people throw different things without changing the sticker. What is inside it now? Who knows... We need to come closer and check.
|
||||
|
||||
Such a programmer saves a little bit on variable declaration, but looses ten times more on debugging the code.
|
||||
|
||||
An extra variable is good, not evil.
|
||||
[/warn]
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
Каждая строчка решения соответствует одному шагу задачи:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var ourPlanetName = "Земля"; // буквально "название нашей планеты"
|
||||
|
||||
var userName = "Петя"; // "имя посетителя"
|
||||
```
|
||||
|
||||
Названия переменных можно бы сократить, например, до `planet` и `name`, но тогда станет менее понятно, о чем речь.
|
||||
|
||||
Насколько допустимы такие сокращения -- зависит от скрипта, его размера и сложности, от того, есть ли другие планеты и пользователи. В общем, лучше не жалеть букв и называть переменные так, чтобы по имени можно было легко понять, что в ней находится, и нельзя было перепутать переменные.
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
# Объявление переменных
|
||||
|
||||
[importance 3]
|
||||
|
||||
<ol>
|
||||
<li>Создайте переменную для названия нашей планеты и присвойте ей значение `"Земля"`. *Правильное* имя выберите сами.</li>
|
||||
<li>Создайте переменную для имени посетителя со значением `"Петя"`. Имя также на ваш вкус.</li>
|
||||
</ol>
|
|
@ -1,120 +0,0 @@
|
|||
# Правильный выбор имени переменной
|
||||
|
||||
Правильный выбор имени переменной -- одна из самых важных и сложных вещей в программировании, которая отличает начинающего от гуру.
|
||||
|
||||
[cut]
|
||||
|
||||
Дело в том, что большинство времени мы тратим не на изначальное написание кода, а на его развитие.
|
||||
|
||||
Возможно, эти слова не очевидны, если вы пока что ничего большого не писали или пишете код "только для чтения" (написал 5 строк, отдал заказчику и забыл). Но чем более серьёзные проекты вы будете делать, тем более актуальны они будут для вас.
|
||||
|
||||
Что такое это "развитие"? Это когда я вчера написал код, а сегодня (или спустя неделю) прихожу и хочу его поменять. Например, вывести сообщение не так, а эдак... Обработать товары по-другому, добавить функционал.. А где у меня там сообщение хранится? А где товар?...
|
||||
|
||||
Гораздо проще найти нужные данные, если они правильно помечены, то есть когда переменная названа *правильно*.
|
||||
|
||||
## Правила именования
|
||||
|
||||
<ul>
|
||||
<li>**Правило 1.**
|
||||
|
||||
**Никакого транслита. Только английский.**
|
||||
|
||||
Неприемлемы:
|
||||
|
||||
```js
|
||||
var moiTovari;
|
||||
var cena;
|
||||
var ssilka;
|
||||
```
|
||||
|
||||
Подойдут:
|
||||
|
||||
```js
|
||||
var myGoods;
|
||||
var price;
|
||||
var link;
|
||||
```
|
||||
|
||||
Чем плох транслит?
|
||||
|
||||
Во-первых, среди разработчиков всего мира принято использовать английский язык для имён переменных. И если ваш код потом попадёт к кому-то другому, например вы будете в команде больше чем из одного человека, то велик шанс, что транслит ему не понравится.
|
||||
|
||||
Во-вторых, русский транслит хуже читается и длиннее, чем названия на английском.
|
||||
|
||||
В-третьих, в проектах вы наверняка будете применять библиотеки, написанные другими людьми. Многое уже готово, в распоряжении современного разработчика есть масса инструментов, все они используют названия переменных и функций на английском языке, и вы, конечно, будете их использовать. А от кода, где транслит перемешан с английским -- волосы могут встать дыбом, и не только на голове.
|
||||
|
||||
Если вы вдруг не знаете английский -- самое время выучить.
|
||||
</li>
|
||||
<li>**Правило 2.**
|
||||
|
||||
**Использовать короткие имена только для переменных "местного значения".**
|
||||
|
||||
Называть переменные именами, не несущими смысловой нагрузки, например `a`, `e`, `p`, `mg` -- можно только в том случае, если они используются в небольшом фрагменте кода и их применение очевидно.
|
||||
|
||||
Вообще же, название переменной должно быть понятным. Иногда для этого нужно использовать несколько слов.
|
||||
</li>
|
||||
<li>**Правило 3.**
|
||||
|
||||
**Переменные из нескольких слов пишутся `вместеВотТак`.**
|
||||
|
||||
Например:
|
||||
|
||||
```js
|
||||
var borderLeftWidth;
|
||||
```
|
||||
|
||||
Этот способ записи называется "верблюжьей нотацией" или, по-английски, "camelCase".
|
||||
|
||||
Существует альтернативный стандарт, когда несколько слов пишутся через знак подчеркивания `'_'`:
|
||||
|
||||
```js
|
||||
var border_left_width;
|
||||
```
|
||||
|
||||
Преимущественно в JavaScript используется вариант `borderLeftWidth`, в частности во встроенных языковых и браузерных функциях. Поэтому целесообразно остановиться на нём.
|
||||
|
||||
Ещё одна причина выбрать "верблюжью нотацию" -- запись в ней немного короче, чем c подчеркиванием, т.к. не нужно вставлять `'_'`.
|
||||
</li>
|
||||
<li>**Правило последнее, главное.**
|
||||
|
||||
**Имя переменной должно максимально чётко соответствовать хранимым в ней данным.**
|
||||
|
||||
Придумывание таких имен -- одновременно коротких и точных, при которых всегда понятно, что где лежит, приходит с опытом, но только если сознательно стремиться к этому.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
Позвольте поделиться одним небольшим секретом, который очень прост, но позволит улучшить названия переменных и сэкономит время.
|
||||
|
||||
Бывает так, что, написав код, мы через некоторое время к нему возвращаемся, надо что-то поправить. И мы примерно помним, что переменная, в которой хранится нужное вам значение, называется... Ну, скажем, `borderLeftWidth`. Мы ищем в её в коде, не находим, но, разобравшись, обнаруживаем, что на самом деле переменная называлась вот так: `leftBorderWidth`.
|
||||
|
||||
**Если мы ищем переменную с одним именем, а находим -- с другим, то зачастую самый лучший ход -- это *переименовать* переменную, чтобы имя было тем, которое вы искали.**
|
||||
|
||||
То есть, в коде `leftBorderWidth`, а мы её переименуем на ту, которую искали: `borderLeftWidth`.
|
||||
|
||||
Зачем? Дело в том, что в следующий раз, когда вы захотите что-то поправить, то вы будете искать по тому же самому имени. Соответственно, это сэкономит вам время.
|
||||
|
||||
Есть причина и поважнее. Поскольку именно это имя переменной пришло в голову -- скорее всего, оно больше соответствует хранимым там данным, чем то, которое было мы придумали изначально. Исключения бывают, но в любом случае -- такое несовпадение -- это повод задуматься.
|
||||
|
||||
Чтобы удобно переименовывать переменную, нужно использовать [хороший редактор JavaScript](/editor), тогда этот процесс будет очень простым и быстрым.
|
||||
|
||||
[smart header="Если коротко..."]
|
||||
Смысл имени переменной -- это "имя на коробке", по которому мы сможем максимально быстро находить нужные нам данные.
|
||||
|
||||
**Не нужно бояться переименовывать переменные, если вы придумали имя получше.**
|
||||
|
||||
Современные редакторы позволяют делать это очень удобно и быстро. Это в конечном счете сэкономит вам время.
|
||||
[/smart]
|
||||
|
||||
|
||||
[warn header="Храните в переменной то, что следует"]
|
||||
Бывают ленивые программисты, которые, вместо того чтобы объявить новую переменную, используют существующую.
|
||||
|
||||
В результате получается, что такая переменная -- как коробка, в которую кидают то одно, то другое, то третье, при этом не меняя название. Что в ней лежит сейчас? А кто его знает... Нужно подойти, проверить.
|
||||
|
||||
Сэкономит такой программист время на объявлении переменной -- потеряет в два раза больше на отладке кода.
|
||||
|
||||
**"Лишняя" переменная -- добро, а не зло.**
|
||||
[/warn]
|
||||
|
||||
|
||||
|
|
@ -1,94 +1,113 @@
|
|||
# Шесть типов данных, typeof
|
||||
# Data types
|
||||
|
||||
В JavaScript существует несколько основных типов данных.
|
||||
There are 7 data types in JavaScript.
|
||||
|
||||
В этой главе мы получим о них общее представление, а позже, в соответствующих главах подробно познакомимся с использованием каждого типа в отдельности.
|
||||
Here we will get the common understanding of them. In the next chapters we'll talk about each type in detail.
|
||||
|
||||
[cut]
|
||||
|
||||
## Число "number"
|
||||
## A number
|
||||
|
||||
```js
|
||||
var n = 123;
|
||||
n = 12.345;
|
||||
```
|
||||
|
||||
Единый тип *число* используется как для целых, так и для дробных чисел.
|
||||
There is a single *number* type for both integer and floating point numbers.
|
||||
|
||||
Существуют специальные числовые значения `Infinity` (бесконечность) и `NaN` (ошибка вычислений).
|
||||
Besides numbers it may store so called "numeric values": `Infinity`, `-Infinity` and `NaN`.
|
||||
|
||||
Например, бесконечность `Infinity` получается при делении на ноль:
|
||||
`Infinity` is meant to represent the mathematical [Infinity](https://en.wikipedia.org/wiki/Infinity).
|
||||
|
||||
We can get it dividing by zero:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
alert( 1 / 0 ); // Infinity
|
||||
alert( -1 / 0 ); // -Infinity
|
||||
```
|
||||
|
||||
Ошибка вычислений `NaN` будет результатом некорректной математической операции, например:
|
||||
`NaN` represents a computational error. It is the result of an incorrect or undefined mathematical operation, for instance:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
alert( "нечисло" * 2 ); // NaN, ошибка
|
||||
alert( "not a number" * 2 ); // NaN
|
||||
```
|
||||
|
||||
Эти значения формально принадлежат типу "число", хотя, конечно, числами в их обычном понимании не являются.
|
||||
These values formally belong to the "number" type. Of course they are not numbers in a common sense of this word.
|
||||
|
||||
Особенности работы с числами в JavaScript разобраны в главе [](/number).
|
||||
We'll cover working with numbers in the chapter [](/number).
|
||||
|
||||
## Строка "string"
|
||||
## A string
|
||||
|
||||
```js
|
||||
var str = "Мама мыла раму";
|
||||
str = 'Одинарные кавычки тоже подойдут';
|
||||
var str = "Hello";
|
||||
var str2 = 'Single quotes are ok too';
|
||||
var prase = `can embed ${str}`;
|
||||
```
|
||||
|
||||
**В JavaScript одинарные и двойные кавычки равноправны.** Можно использовать или те или другие.
|
||||
In JavaScript, there are 3 types of quotes.
|
||||
|
||||
[smart header="Тип *символ* не существует, есть только *строка*."]
|
||||
В некоторых языках программирования есть специальный тип данных для одного символа. Например, в языке С это `char`. В JavaScript есть только тип "строка" `string`. Что, надо сказать, вполне удобно.
|
||||
<ol>
|
||||
<li>Double quotes and single quotes are essentially the same. Can use either.</li>
|
||||
<li>Backtricks are "extended functionality" quotes. They allow to embed other variables or even expressions into the string wrapping them by `${…}`.</li>
|
||||
</ol>
|
||||
|
||||
[smart header="There is no *character* type."]
|
||||
In some languages, there is a special "character" type for a single character. For example, in the C language it is `char`.
|
||||
|
||||
In JavaScript, there is only one type: `string`.
|
||||
[/smart]
|
||||
|
||||
Более подробно со строками мы познакомимся в главе [](/string).
|
||||
We'll cover strings more thoroughly in the chapter [](/string).
|
||||
|
||||
## Булевый (логический) тип "boolean"
|
||||
## Boolean (logical) type
|
||||
|
||||
У него всего два значения: `true` (истина) и `false` (ложь).
|
||||
The boolean type has only two values in it: `true` and `false`.
|
||||
|
||||
Как правило, такой тип используется для хранения значения типа да/нет, например:
|
||||
This type is commonly used to store the yes/no values.
|
||||
|
||||
For instance:
|
||||
|
||||
```js
|
||||
//+ no-beautify
|
||||
var checked = true; // поле формы помечено галочкой
|
||||
checked = false; // поле формы не содержит галочки
|
||||
var checked = true; // the form field is checked
|
||||
checked = false; // the form field is not checked
|
||||
```
|
||||
|
||||
О нём мы поговорим более подробно, когда будем обсуждать логические вычисления и условные операторы.
|
||||
We'll cover booleans while discussing logical operators.
|
||||
|
||||
## Специальное значение "null"
|
||||
## The "null" value
|
||||
|
||||
Значение `null` не относится ни к одному из типов выше, а образует свой отдельный тип, состоящий из единственного значения `null`:
|
||||
The special `null` value does not belong to any type described above.
|
||||
|
||||
It forms a separate type of its own, which contains only the `null` value:
|
||||
|
||||
```js
|
||||
var age = null;
|
||||
```
|
||||
|
||||
В JavaScript `null` не является "ссылкой на несуществующий объект" или "нулевым указателем", как в некоторых других языках. Это просто специальное значение, которое имеет смысл "ничего" или "значение неизвестно".
|
||||
In JavaScript `null` is not a "reference to a non-existing object" or a "null pointer" like in some other languages.
|
||||
|
||||
В частности, код выше говорит о том, что возраст `age` неизвестен.
|
||||
It's just a special value which has the sense of "nothing" or "value unknown".
|
||||
|
||||
## Специальное значение "undefined"
|
||||
The code above basically says that the `age` is unknown.
|
||||
|
||||
Значение `undefined`, как и `null`, образует свой собственный тип, состоящий из одного этого значения. Оно имеет смысл "значение не присвоено".
|
||||
## The "undefined" value
|
||||
|
||||
Если переменная объявлена, но в неё ничего не записано, то её значение как раз и есть `undefined`:
|
||||
The special value `undefined` stands separately. It makes a type of its own, just like `null`.
|
||||
|
||||
The sense of `undefined` is "value is not assigned".
|
||||
|
||||
If a variable is declared, but not assigned, then its value is exactly `undefined`:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var x;
|
||||
alert( x ); // выведет "undefined"
|
||||
alert( x ); // shows "undefined"
|
||||
```
|
||||
|
||||
Можно присвоить `undefined` и в явном виде, хотя это делается редко:
|
||||
Technically, it is possible to assign to `undefined`:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
|
@ -98,37 +117,90 @@ x = undefined;
|
|||
alert( x ); // "undefined"
|
||||
```
|
||||
|
||||
В явном виде `undefined` обычно не присваивают, так как это противоречит его смыслу. Для записи в переменную "пустого" или "неизвестного" значения используется `null`.
|
||||
...But it's not recommended to do that, because such assignment contradicts to the sense of `undefined`.
|
||||
|
||||
## Объекты "object"
|
||||
To write an "empty" or an "unknown" value into the variable, use `null`.
|
||||
|
||||
Первые 5 типов называют *"примитивными"*.
|
||||
|
||||
Особняком стоит шестой тип: *"объекты"*.
|
||||
## Symbols and objects
|
||||
|
||||
Он используется для коллекций данных и для объявления более сложных сущностей.
|
||||
|
||||
Объявляются объекты при помощи фигурных скобок `{...}`, например:
|
||||
The "symbol" type is used to create unique identifiers.
|
||||
|
||||
```js
|
||||
var user = { name: "Вася" };
|
||||
//+ run
|
||||
var s = Symbol();
|
||||
```
|
||||
|
||||
Мы подробно разберём способы объявления объектов и, вообще, работу с объектами, позже, в главе [](/object).
|
||||
Symbols are mainly used for objects and thus we'll cover
|
||||
|
||||
## Оператор typeof [#type-typeof]
|
||||
|
||||
Оператор `typeof` возвращает тип аргумента.
|
||||
|
||||
У него есть два синтаксиса: со скобками и без:
|
||||
```js
|
||||
//+ run
|
||||
var s = Symbol("id");
|
||||
|
||||
x = undefined;
|
||||
|
||||
alert( x ); // "undefined"
|
||||
```
|
||||
|
||||
|
||||
## Object
|
||||
|
||||
The `object` type is special.
|
||||
|
||||
All other types are called "primitive", because their values can contain only a single thing (be it a string or a number or whatever).
|
||||
|
||||
In contrast, objects are used to store collections of various data and more complex entities.
|
||||
|
||||
An object is defined with the figure brackets `{…}`.
|
||||
|
||||
For instance, here we create a `user` object with the name and the age:
|
||||
|
||||
```js
|
||||
var user = {
|
||||
name: "John",
|
||||
age: 30
|
||||
};
|
||||
```
|
||||
|
||||
We can access the data form the object via the dot notation:
|
||||
|
||||
```js
|
||||
alert( user.name ); // John
|
||||
alert( user.age ); // 30
|
||||
```
|
||||
|
||||
We'll cover working with objects in the chapter [](/object).
|
||||
|
||||
## Symbol
|
||||
|
||||
The `symbol` type is used to create unique identifiers for objects.
|
||||
|
||||
```js
|
||||
var id = Symbol("id");
|
||||
```
|
||||
|
||||
There are other programming languages with a "symbol" type, namely Ruby.
|
||||
|
||||
Let's just say that JavaScript symbols are not the same.
|
||||
|
||||
We list symbols here for completeness, their in-depth study goes after covering objects.
|
||||
|
||||
## The typeof operator [#type-typeof]
|
||||
|
||||
The `typeof` operator returns the type of the argument.
|
||||
|
||||
It has two syntaxes: with the brackets or without them.
|
||||
|
||||
<ol>
|
||||
<li>Синтаксис оператора: `typeof x`.</li>
|
||||
<li>Синтаксис функции: `typeof(x)`.</li>
|
||||
<li>As an operator: `typeof x`.</li>
|
||||
<li>Function style: `typeof(x)`.</li>
|
||||
</ol>
|
||||
|
||||
Работают они одинаково, но первый синтаксис короче.
|
||||
They work the same.
|
||||
|
||||
**Результатом `typeof` является строка, содержащая тип:**
|
||||
The result of `typeof x` is a string, which has the type name:
|
||||
|
||||
```js
|
||||
typeof undefined // "undefined"
|
||||
|
@ -139,6 +211,8 @@ typeof true // "boolean"
|
|||
|
||||
typeof "foo" // "string"
|
||||
|
||||
typeof Symbol("id") // "symbol"
|
||||
|
||||
typeof {} // "object"
|
||||
|
||||
*!*
|
||||
|
@ -150,19 +224,18 @@ typeof function(){} // "function" (2)
|
|||
*/!*
|
||||
```
|
||||
|
||||
Последние две строки помечены, потому что `typeof` ведет себя в них по-особому.
|
||||
Please note the last two lines, because `typeof` behaves specially there.
|
||||
|
||||
<ol>
|
||||
<li>Результат `typeof null == "object"` -- это официально признанная ошибка в языке, которая сохраняется для совместимости. На самом деле `null` -- это не объект, а отдельный тип данных.</li>
|
||||
<li>Функции мы пройдём чуть позже. Пока лишь заметим, что функции не являются отдельным базовым типом в JavaScript, а подвидом объектов. Но `typeof` выделяет функции отдельно, возвращая для них `"function"`. На практике это весьма удобно, так как позволяет легко определить функцию.</li>
|
||||
<li>The result of `typeof null` equals to `"object"`. That is an officially recognized error in the language that is kept for compatibility. In fact, `null` is not an object, but a special value from a data type of its own.</li>
|
||||
<li>Functions are yet to be covered. As of now let's just note that functions is a kind of objects. But `typeof` treats them separately returning `"function"`. That's very convenient in practie.</li>
|
||||
</ol>
|
||||
|
||||
К работе с типами мы также вернёмся более подробно в будущем, после изучения основных структур данных.
|
||||
## Summary
|
||||
|
||||
## Итого
|
||||
<ul>
|
||||
<li>There are 7 basic types in JavaScript. Six "primitive" types: `number`, `string`, `boolean`, `null`, `undefined`, `symbol` and `object`.</li>
|
||||
<li>Use `typeof x` to see which type is stored in `x`, but note that `typeof null` is mistakingly returned as undefined.</li>
|
||||
</ul>
|
||||
|
||||
Есть 5 "примитивных" типов: `number`, `string`, `boolean`, `null`, `undefined` и 6-й тип -- объекты `object`.
|
||||
|
||||
Очень скоро мы изучим их во всех деталях.
|
||||
|
||||
Оператор `typeof x` позволяет выяснить, какой тип находится в `x`, возвращая его в виде строки.
|
||||
Now as we know which types exist, let's move on to operators and compute something using these types.
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
# Основные операторы
|
||||
# Operators
|
||||
|
||||
Для работы с переменными, со значениями, JavaScript поддерживает все стандартные операторы, большинство которых есть и в других языках программирования.
|
||||
Many operators are known to us from the school program. It is an addition `+`, a multiplication `*`, a subsctraction and so on.
|
||||
|
||||
Несколько операторов мы знаем со школы -- это обычные сложение `+`, умножение `*`, вычитание и так далее.
|
||||
|
||||
В этой главе мы сконцентрируемся на операторах, которые в курсе математики не проходят, и на их особенностях в JavaScript.
|
||||
In this chapter we mainly concentrate on aspects not covered by the arithmetic.
|
||||
[cut]
|
||||
|
||||
## Термины: "унарный", "бинарный", "операнд"
|
||||
## Terms: "unary", "binary", "operand"
|
||||
|
||||
У операторов есть своя терминология, которая используется во всех языках программирования.
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue