From 980fe00a74a9ad013b945755415ace2e5429c3c2 Mon Sep 17 00:00:00 2001 From: Alexey Pyltsyn Date: Wed, 27 Oct 2021 02:31:24 +0300 Subject: [RU] Remove notranslate (#2874) --- .../javascript/asynchronous/async_await/index.html | 44 +++++++-------- .../javascript/asynchronous/concepts/index.html | 18 +++--- .../javascript/asynchronous/introducing/index.html | 22 ++++---- .../asynchronous/timeouts_and_intervals/index.html | 64 +++++++++++----------- .../building_blocks/conditionals/index.html | 54 +++++++++--------- .../javascript/building_blocks/events/index.html | 56 +++++++++---------- .../building_blocks/functions/index.html | 64 +++++++++++----------- .../building_blocks/looping_code/index.html | 52 +++++++++--------- .../client-side_storage/index.html | 58 ++++++++++---------- .../client-side_web_apis/introduction/index.html | 22 ++++---- .../manipulating_documents/index.html | 38 ++++++------- .../first_steps/a_first_splash/index.html | 50 ++++++++--------- .../first_steps/silly_story_generator/index.html | 2 +- .../javascript/first_steps/strings/index.html | 34 ++++++------ .../first_steps/useful_string_methods/index.html | 44 +++++++-------- .../javascript/first_steps/variables/index.html | 48 ++++++++-------- .../ru/learn/javascript/objects/basics/index.html | 52 +++++++++--------- .../javascript/objects/inheritance/index.html | 22 ++++---- .../objects/object-oriented_js/index.html | 32 +++++------ .../objects/object_building_practice/index.html | 24 ++++---- 20 files changed, 400 insertions(+), 400 deletions(-) (limited to 'files/ru/learn/javascript') diff --git a/files/ru/learn/javascript/asynchronous/async_await/index.html b/files/ru/learn/javascript/asynchronous/async_await/index.html index 7280fe9843..e64c9cc30b 100644 --- a/files/ru/learn/javascript/asynchronous/async_await/index.html +++ b/files/ru/learn/javascript/asynchronous/async_await/index.html @@ -36,36 +36,36 @@ translation_of: Learn/JavaScript/Asynchronous/Async_await

Попробуйте выполнить в консоли браузера следующий код:

-
function hello() { return "Hello" };
+
function hello() { return "Hello" };
 hello();

Функция возвращает "Hello" — ничего необычного, верно ?

Но что если мы сделаем её асинхронной ? Проверим:

-
async function hello() { return "Hello" };
+
async function hello() { return "Hello" };
 hello();

Как было сказано ранее, вызов асинхронной функции возвращает объект Promise.

Вот пример с async function expression:

-
let hello = async function() { return "Hello" };
+
let hello = async function() { return "Hello" };
 hello();

Также можно использовать стрелочные функции:

-
let hello = async () => { return "Hello" };
+
let hello = async () => { return "Hello" };

Все они в общем случае делают одно и то же.

Чтобы получить значение, которое возвращает Promise, мы как обычно можем использовать метод .then():

-
hello().then((value) => console.log(value))
+
hello().then((value) => console.log(value))

или ещё короче

-
hello().then(console.log)
+
hello().then(console.log)
 

Итак, ключевое слово async, превращает обычную функцию в асинхронную и результат вызова функции оборачивает в Promise. Также асинхронная функция позволяет использовать в своём теле ключевое слово await, о котором далее.

@@ -78,7 +78,7 @@ hello();

Небольшой пример:

-
async function hello() {
+
async function hello() {
   return greeting = await Promise.resolve("Hello");
 };
 
@@ -90,7 +90,7 @@ hello().then(alert);

Давайте посмотрим на пример из предыдущей статьи:

-
fetch('coffee.jpg')
+
fetch('coffee.jpg')
 .then(response => {
   if (!response.ok) {
     throw new Error(`HTTP error! status: ${response.status}`);
@@ -110,7 +110,7 @@ hello().then(alert);

К этому моменту вы должны понимать как работают Promises, чтобы понять все остальное. Давайте перепишем код используя async/await и оценим разницу.

-
async function myFetch() {
+
async function myFetch() {
   let response = await fetch('coffee.jpg');
 
   if (!response.ok) {
@@ -134,7 +134,7 @@ myFetch()
 
 

Так как ключевое слово async заставляет функцию вернуть Promise, мы можем использовать гибридный подход:

-
async function myFetch() {
+
async function myFetch() {
   let response = await fetch('coffee.jpg');
   if (!response.ok) {
     throw new Error(`HTTP error! status: ${response.status}`);
@@ -160,7 +160,7 @@ myFetch().then((blob) => {
  
Пример:

-
let response = await fetch('coffee.jpg');
+
let response = await fetch('coffee.jpg');

Значение Promise, которое вернёт fetch() будет присвоено переменной response только тогда, когда оно будет доступно - парсер делает паузу на данной строке дожидаясь этого момента. Как только значение доступно, парсер переходит к следующей строке, в которой создаётся объект Blob из результата Promise. В этой строке, кстати, также используется await, потому что метод .blob() также возвращает Promise. Когда результат готов, мы возвращаем его наружу из myFetch().

@@ -175,7 +175,7 @@ myFetch().then((blob) => {

Мы можем использовать синхронную try...catch структуру с async/await. Вот изменённая версия первого примера выше:

-
async function myFetch() {
+
async function myFetch() {
   try {
     let response = await fetch('coffee.jpg');
 
@@ -199,7 +199,7 @@ myFetch();

Если вы хотите использовать гибридный подходы (пример выше), лучше использовать блок .catch() после блока .then() вот так:

-
async function myFetch() {
+
async function myFetch() {
   let response = await fetch('coffee.jpg');
   if (!response.ok) {
     throw new Error(`HTTP error! status: ${response.status}`);
@@ -233,7 +233,7 @@ myFetch().then((blob) => {
 
 

Версия с async/await (смотрите live demo и source code), сейчас выглядит так:

-
async function fetchAndDecode(url, type) {
+
async function fetchAndDecode(url, type) {
   let response = await fetch(url);
 
   let content;
@@ -282,7 +282,7 @@ displayContent()
 
 

Вы видите, что мы легко изменили fetchAndDecode() функцию в асинхронный вариант. Взгляните на строку с Promise.all():

-
let values = await Promise.all([coffee, tea, description]);
+
let values = await Promise.all([coffee, tea, description]);

С помощью await мы ждём массив результатов всех трёх Promises и присваиваем его в переменную values. Это асинхронный код, но он написан в синхронном стиле, за счёт чего он гораздо читабельнее.

@@ -306,7 +306,7 @@ displayContent()

Мы подготовили два примера  — slow-async-await.html (см. source code) и fast-async-await.html (см. source code). Они оба начинаются с функции возвращающей promise, имитирующей асинхронность процессов при помощи вызова setTimeout():

-
function timeoutPromise(interval) {
+
function timeoutPromise(interval) {
   return new Promise((resolve, reject) => {
     setTimeout(function(){
       resolve("done");
@@ -316,13 +316,13 @@ displayContent()
 
 

Далее в каждом примере есть асинхронная функция  timeTest() ожидающая три вызова timeoutPromise():

-
async function timeTest() {
+
async function timeTest() {
   ...
 }

В каждом примере функция записывает время начала исполнения и сколько времени понадобилось на исполнение  timeTest()  промисов, вычитая время в момент запуска функции из времени в момент разрешения промисов:

-
let startTime = Date.now();
+
let startTime = Date.now();
 timeTest().then(() => {
   let finishTime = Date.now();
   let timeTaken = finishTime - startTime;
@@ -333,7 +333,7 @@ timeTest().then(() => {
 
 

В случае с медленным примером slow-async-await.html, timeTest() выглядит:

-
async function timeTest() {
+
async function timeTest() {
   await timeoutPromise(3000);
   await timeoutPromise(3000);
   await timeoutPromise(3000);
@@ -343,7 +343,7 @@ timeTest().then(() => {
 
 

Во втором  fast-async-await.html примере, функция timeTest() выглядит как:

-
async function timeTest() {
+
async function timeTest() {
   const timeoutPromise1 = timeoutPromise(3000);
   const timeoutPromise2 = timeoutPromise(3000);
   const timeoutPromise3 = timeoutPromise(3000);
@@ -365,7 +365,7 @@ timeTest().then(() => {
 
 

В качестве последнего замечания, вы можете использовать  async  перед методами классов или объектов, вынуждая их возвращать promises. А также  await внутри методов объявленных таким образом. Посмотрите на пример ES class code, который мы наблюдали в статье  object-oriented JavaScript,  и сравните его с модифицированной (асинхронной) async версией ниже:

-
class Person {
+
class Person {
   constructor(first, last, age, gender, interests) {
     this.name = {
       first,
@@ -389,7 +389,7 @@ let han = new Person('Han', 'Solo', 25, 'male', ['Smuggling']);

Первый метод класса теперь можно использовать таким образом:

-
han.greeting().then(console.log);
+
han.greeting().then(console.log);

Browser support (Поддержка браузерами)

diff --git a/files/ru/learn/javascript/asynchronous/concepts/index.html b/files/ru/learn/javascript/asynchronous/concepts/index.html index bdc84b6f72..fe4e6c7343 100644 --- a/files/ru/learn/javascript/asynchronous/concepts/index.html +++ b/files/ru/learn/javascript/asynchronous/concepts/index.html @@ -45,7 +45,7 @@ translation_of: Learn/JavaScript/Asynchronous/Concepts

В нашем simple-sync.html примере (see it running live), добавим кнопке событие на клик, чтобы при нажатии на неё запускалась трудоёмкая операция (расчёт 10000000 дат, и вывод последней рассчитанной даты на консоль) после чего в DOM добавляется ещё один параграф:

-
const btn = document.querySelector('button');
+
const btn = document.querySelector('button');
 btn.addEventListener('click', () => {
   let myDate;
   for(let i = 0; i < 10000000; i++) {
@@ -75,7 +75,7 @@ btn.addEventListener('click', () => {
  
  • Кнопка "Click me for alert", при нажатии показывает предупреждение.
  • -
    function expensiveOperation() {
    +
    function expensiveOperation() {
       for(let i = 0; i < 1000000; i++) {
         ctx.fillStyle = 'rgba(0,0,255, 0.2)';
         ctx.beginPath();
    @@ -102,24 +102,24 @@ alertBtn.addEventListener('click', () =>
     
     

    Под потоком, обычно, понимают одиночный процесс, который может использовать программа, для выполнения своих нужд. Каждый поток может выполнять только одну в текущий момент времени:

    -
    Task A --> Task B --> Task C
    +
    Task A --> Task B --> Task C

    Каждая задача будет выполнена последовательно; только когда текущая задача завершится, следующая сможет начаться.

    Как мы говорили выше, большинство компьютеров теперь имеют процессор с несколькими ядрами, т.е. могут выполнять несколько задач одновременно. Языки программирования, поддерживающие многопоточность, могут использовать несколько ядер, чтобы выполнять несколько задач одновременно:

    -
    Thread 1: Task A --> Task B
    +
    Thread 1: Task A --> Task B
     Thread 2: Task C --> Task D

    JavaScript однопоточный

    JavaScript, традиционно для скриптовых языков, однопоточный. Даже, если есть несколько ядер, вы можете использовать их только для выполнения задач в одном потоке, называемом основной поток. Наш пример выше, выполняется следующим образом:

    -
    Main thread: Render circles to canvas --> Display alert()
    +
    Main thread: Render circles to canvas --> Display alert()

    В итоге, JavaScript получил несколько инструментов, которые могут помочь в решении подобных проблем. Web workers позволяют вам обработать некоторый JavaScript-код в отдельном потоке, который называется обработчик, таким образом вы можете запускать отдельные блоки JavaScript-кода одновременно. В основном, вы будете использовать воркеры, чтобы запустить ресурсоёмкий процесс, отдельно от основного потока, чтобы не блокировать действия пользователя.

    -
      Main thread: Task A --> Task C
    +
      Main thread: Task A --> Task C
     Worker thread: Expensive task B

    Помня об этом, выполните наш следующий пример simple-sync-worker.html (посмотреть пример в действии), с открытой консолью. Это переписанный предыдущий пример, который теперь рассчитывает 10 миллионов дат в отдельном потоке обработчика. Теперь, когда вы нажимаете на кнопку, браузер может добавить новый элемент на страницу, до того как все даты будут посчитаны. Самая первая операция больше не блокирует выполнение следующей.

    @@ -130,18 +130,18 @@ Worker thread: Expensive task B

    Следующая проблема заключается в том, что даже если код запущенный в воркере ничего не блокирует, он в целом остаётся синхронным. Это проблема появляется, когда какой-то функции требуются результаты выполнения нескольких предыдущих функций. Рассмотрим следующую диаграмму потоков:

    -
    Main thread: Task A --> Task B
    +
    Main thread: Task A --> Task B

    В этом примере, предположим Task A делает что-то вроде получения картинки с сервера а Task B затем делает что-нибудь с полученной картинкой, например, применяет к ней фильтр. Если запустить выполняться Task A и тут же попытаться выполнить Task B, то вы получите ошибку, поскольку картинка ещё не будет доступна.

    -
      Main thread: Task A --> Task B --> |Task D|
    +
      Main thread: Task A --> Task B --> |Task D|
     Worker thread: Task C -----------> |      |

    Теперь, давайте предположим, что Task D использует результат выполнения обеих задач Task B и Task C. Если мы уверенны, что оба результата будут доступны одновременно, тогда не возникнет проблем, однако, часто это не так. Если Task D попытаться запустить, когда какого-то нужного ей результата ещё нет, выполнение закончится ошибкой.

    Чтобы избежать подобных проблем, браузеры позволяют нам выполнять определённые операции асинхронно. Такие возможности, как Promises позволяют запустить некоторую операцию (например, получение картинки с сервера), и затем подождать пока операция не вернёт результат, перед тем как начать выполнение другой задачи:

    -
    Main thread: Task A                   Task B
    +
    Main thread: Task A                   Task B
         Promise:      |__async operation__|

    Поскольку операция выполняется где-то отдельно, основной поток не блокируется, при выполнении асинхронных задач.

    diff --git a/files/ru/learn/javascript/asynchronous/introducing/index.html b/files/ru/learn/javascript/asynchronous/introducing/index.html index 2d457b6888..0b53770834 100644 --- a/files/ru/learn/javascript/asynchronous/introducing/index.html +++ b/files/ru/learn/javascript/asynchronous/introducing/index.html @@ -36,7 +36,7 @@ translation_of: Learn/JavaScript/Asynchronous/Introducing

    Большая часть функциональности, которую мы рассматривали в предыдущих обучающих модулях, является синхронной — вы запускаете какой-то код, а результат возвращается, как только браузер может его вернуть. Давайте рассмотрим простой пример ( посмотрите онлайн, как это работает и посмотрите исходный код):

    -
    const btn = document.querySelector('button');
    +
    const btn = document.querySelector('button');
     btn.addEventListener('click', () => {
       alert('You clicked me!');
     
    @@ -65,7 +65,7 @@ btn.addEventListener('click', () => {
     

    Так и в примере выше: после нажатия кнопки абзац не сможет появиться пока не будет нажата кнопка OK в окне сообщения. Попробуйте сами:

    {{EmbedLiveSample('Синхронный_JavaScript', '100%', '70px')}}

    @@ -80,7 +80,7 @@ btn.addEventListener('click', () => {

    Почему трудно работать, используя синхронный код? Давайте посмотрим на небольшой пример. Когда вы получаете картинку с сервера, вы не можете мгновенно вернуть результат. Это значит что следующий (псевдо) код не сработает:

    -
    let response = fetch('myImage.png');
    +
    let response = fetch('myImage.png');
     let blob = response.blob();
     // display your image blob in the UI somehow
    @@ -94,7 +94,7 @@ let blob = response.blob();

    Пример асинхронного колбэка вторым параметром {{domxref("EventTarget.addEventListener", "addEventListener()")}} (как мы видели выше):

    -
    btn.addEventListener('click', () => {
    +
    btn.addEventListener('click', () => {
       alert('You clicked me!');
     
       let pElem = document.createElement('p');
    @@ -108,7 +108,7 @@ let blob = response.blob();
     
     

    Вы можете написать свою собственную функцию, содержащую колбэк-функцию. Давайте взглянем на ещё один пример, в котором происходит загрузка ресурсов через XMLHttpRequest API (запустите пример, и посмотрите исходный код):

    -
    function loadAsset(url, type, callback) {
    +
    function loadAsset(url, type, callback) {
       let xhr = new XMLHttpRequest();
       xhr.open('GET', url);
       xhr.responseType = type;
    @@ -136,7 +136,7 @@ loadAsset('coffee.jpg', 'blob', displayImage);

    Заметьте, что не все колбэк-функции асинхронны — некоторые запускаются синхронно. Например, при использовании {{jsxref("Array.prototype.forEach()")}} для перебора элементов массива (запустите пример, и посмотрите исходный код):

    -
    const gods = ['Apollo', 'Artemis', 'Ares', 'Zeus'];
    +
    const gods = ['Apollo', 'Artemis', 'Ares', 'Zeus'];
     
     gods.forEach(function (eachName, index){
       console.log(index + '. ' + eachName);
    @@ -148,7 +148,7 @@ gods.forEach(function (eachName, index){
     
     

    Промисы — новый стиль написания асинхронного кода, который используется в современных Web API. Хорошим примером является fetch() API, который современнее и эффективнее чем {{domxref("XMLHttpRequest")}}. Посмотрим на краткий пример, из нашей статьи Fetching data from the server:

    -
    fetch('products.json').then(function(response) {
    +
    fetch('products.json').then(function(response) {
       return response.json();
     }).then(function(json) {
       products = json;
    @@ -195,7 +195,7 @@ gods.forEach(function (eachName, index){
     
     

    Давайте рассмотрим пример, который дополнительно иллюстрирует природу асинхронного кода, показывая, что может произойти, когда мы не полностью осознаем порядок выполнения кода, и проблемы, связанные с попыткой трактовать асинхронный код как синхронный. Следующий пример довольно похож на тот, что мы видели раньше (запустите пример, и посмотреть исходный код). Одно из отличий состоит в том, что мы включили ряд операторов {{domxref("console.log()")}} чтобы проиллюстрировать порядок, в котором, как вы думаете, будет выполняться код.

    -
    console.log ('Starting');
    +
    console.log ('Starting');
     let image;
     
     fetch('coffee.jpg').then((response) => {
    @@ -226,7 +226,7 @@ console.log ('All done!');

    Если вы запутались, рассмотрим следующий небольшой пример:

    -
    console.log("registering click handler");
    +
    console.log("registering click handler");
     
     button.addEventListener('click', () => {
       console.log("get click");
    @@ -240,11 +240,11 @@ console.log("all done");

    Чтобы увидеть это в действии, попробуйте взять локальную копию нашего примера и измените третий вызов console.log () следующим образом:

    -
    console.log ('All done! ' + image + 'displayed.');
    +
    console.log ('All done! ' + image + 'displayed.');

    Теперь вместо третьего сообщения должна возникнуть следующая ошибка:

    -
    TypeError: image is undefined; can't access its "src" property
    +
    TypeError: image is undefined; can't access its "src" property

    Это происходит потому, что в то же время браузер пытается запустить третий console.log(), блок fetch() ещё не закончил выполнение, поэтому переменная image ещё не имеет значения.

    diff --git a/files/ru/learn/javascript/asynchronous/timeouts_and_intervals/index.html b/files/ru/learn/javascript/asynchronous/timeouts_and_intervals/index.html index 8d00ba98af..19019a19a9 100644 --- a/files/ru/learn/javascript/asynchronous/timeouts_and_intervals/index.html +++ b/files/ru/learn/javascript/asynchronous/timeouts_and_intervals/index.html @@ -64,13 +64,13 @@ original_slug: Learn/JavaScript/Asynchronous/Таймауты_и_интерва

    В следующем примере, браузер будет ожидать две секунды перед тем как  выполнит анонимную функцию, тогда отобразит сообщение (живой пример, и исходный код):

    -
    let myGreeting = setTimeout(function() {
    +
    let myGreeting = setTimeout(function() {
       alert('Hello, Mr. Universe!');
     }, 2000)

    Указанные вами функции не обязательно должны быть анонимными. Вы можете дать своей функции имя и даже определить её где-нибудь ещё и передать ссылку на функцию в setTimeout (). Следующие две версии фрагмента кода эквивалентны первой:

    -
    // С именованной функцией
    +
    // С именованной функцией
     let myGreeting = setTimeout(function sayHi() {
       alert('Hello, Mr. Universe!');
     }, 2000)
    @@ -92,19 +92,19 @@ let myGreeting = setTimeout(sayHi, 2000);

    Например, вы можете реорганизовать предыдущую функцию, чтобы она передавала привет любому имени, переданному ей:

    -
    function sayHi(who) {
    +
    function sayHi(who) {
       alert(`Hello ${who}!`);
     }

    Теперь вы можете передать имя в вызов setTimeout () в качестве третьего параметра:

    -
    let myGreeting = setTimeout(sayHi, 2000, 'Mr. Universe');
    +
    let myGreeting = setTimeout(sayHi, 2000, 'Mr. Universe');

    Очистка таймаутов

    Наконец, если был создан тайм-аут, вы можете отменить его до истечения указанного времени, вызвав clearTimeout(), передав ему идентификатор вызова setTimeout() в качестве параметра. Итак, чтобы отменить указанный выше тайм-аут, вы должны сделать следующее:

    -
    clearTimeout(myGreeting);
    +
    clearTimeout(myGreeting);

    Note: См.greeter-app.html для более полной демонстрации, которая позволяет вам указать имя для приветствия и отменить приветствие с помощью отдельной кнопки (см. исходный код).

    @@ -118,7 +118,7 @@ let myGreeting = setTimeout(sayHi, 2000);

    Давайте посмотрим на пример. Следующая функция создаёт новый объект Date(), с помощью toLocaleTimeString() извлекает из него строку с временем и отображает её в пользовательском интерфейсе. Затем он запускает функцию один раз в секунду с помощью setInterval(), создавая эффект цифровых часов, которые обновляются раз в секунду ( реальный пример, и исходный код):

    -
    function displayTime() {
    +
    function displayTime() {
        let date = new Date();
        let time = date.toLocaleTimeString();
        document.getElementById('demo').textContent = time;
    @@ -132,7 +132,7 @@ const createClock = setInterval(displayTime, 1000);

    setInterval () выполняет задачу постоянно. setInterval () продолжает выполнять задачу вечно, если вы что-то с ней не сделаете. Возможно, вам понадобится способ остановить такие задачи, иначе вы можете получить ошибки, если браузер не сможет выполнить какие-либо другие версии задачи или если анимация, обрабатываемая задачей, завершилась. Вы можете сделать это так же, как останавливаете timeouts - передавая идентификатор, возвращаемый вызовом setInterval (), в функцию clearInterval ():

    -
    const myInterval = setInterval(myFunction, 2000);
    +
    const myInterval = setInterval(myFunction, 2000);
     
     clearInterval(myInterval);
    @@ -182,7 +182,7 @@ clearInterval(myInterval);

    В приведённом ниже примере используется рекурсивный setTimeout () для запуска переданной функции каждые 100 миллисекунд:

    -
    let i = 1;
    +
    let i = 1;
     
     setTimeout(function run() {
       console.log(i);
    @@ -192,7 +192,7 @@ setTimeout(function run() {
     
     

    Сравните приведённый выше пример со следующим - здесь используется setInterval () для достижения того же эффекта:

    -
    let i = 1;
    +
    let i = 1;
     
     setInterval(function run() {
       console.log(i);
    @@ -217,7 +217,7 @@ setInterval(function run() {
     
     

    Например, код приведённый ниже (рабочий код) выводит alert содержащий "Hello", затем alert содержащий "World" как только вы нажмёте ОК в первом alert.

    -
    setTimeout(function() {
    +
    setTimeout(function() {
       alert('World');
     }, 0);
     
    @@ -243,7 +243,7 @@ alert('Hello');

    Метод принимает в качестве аргумента колбэк, который должен быть вызван перед перерисовкой. Это общий шаблон, в котором он используется:

    -
    function draw() {
    +
    function draw() {
        // Drawing code goes here
        requestAnimationFrame(draw);
     }
    @@ -272,7 +272,7 @@ draw();

    Давайте поговорим ещё немного о том, чем метод requestAnimationFrame () отличается от других методов, используемых ранее. Глядя на наш код сверху:

    -
    function draw() {
    +
    function draw() {
        // Drawing code goes here
        requestAnimationFrame(draw);
     }
    @@ -281,7 +281,7 @@ draw();

    Такой же код с использованием setInterval():

    -
    function draw() {
    +
    function draw() {
        // Drawing code goes here
     }
     
    @@ -297,7 +297,7 @@ setInterval(draw, 17);

    Это полезно, поскольку позволяет запускать вещи в определённое время и в постоянном темпе, независимо от того, насколько быстрым или медленным может быть ваше устройство. Общий шаблон, который вы бы использовали, выглядит примерно так:

    -
    let startTime = null;
    +
    let startTime = null;
     
     function draw(timestamp) {
         if (!startTime) {
    @@ -337,7 +337,7 @@ draw();
  • Примените следующий CSS к HTML шаблону (любым предпочитаемым способом). Он установ красный фон на странице, высоту <body> равную 100% высоты {{htmlelement("html")}} , и центрирует <div> внутри <body>, по горизонтали и вертикали.

    -
    html {
    +  
    html {
       background-color: white;
       height: 100%;
     }
    @@ -362,7 +362,7 @@ div {
      
  • Разместите следующий JavaScript-код в  <script> . Здесь вы сохраняете ссылку на <div> внутри, устанавливаете для переменной rotateCount значение 0, устанавливаете неинициализированную переменную, которая позже будет использоваться для хранения ссылки на вызов requestAnimationFrame(), и устанавливаете для переменной startTime значение null, которая будет позже использоваться для хранения времени начала requestAnimationFrame().

    -
    const spinner = document.querySelector('div');
    +  
    const spinner = document.querySelector('div');
     let rotateCount = 0;
     let startTime = null;
     let rAF;
    @@ -371,14 +371,14 @@ let rAF;
      
  • Под предыдущим кодом вставьте функцию draw() которая будет использоваться для хранения нашего кода анимации, который включает параметр timestamp :

    -
    function draw(timestamp) {
    +  
    function draw(timestamp) {
     
     }
  • Внутри draw () добавьте следующие строки. Они определят время начала, если оно ещё не определено (это произойдёт только на первой итерации цикла), и установят для параметра rotateCount значение для поворота счётчика (текущая временная метка, возьмите начальную временную метку, разделённую на три, чтобы замедлиться):

    -
      if (!startTime) {
    +  
      if (!startTime) {
        startTime = timestamp;
       }
     
    @@ -388,22 +388,22 @@ let rAF;
      
  • Под предыдущей строкой внутри draw () добавьте следующий блок - он проверяет, превышает ли значение rotateCount 359 (например, 360, полный круг). Если это так, он устанавливает значение по модулю 360 (то есть остаток, оставшийся после деления значения на 360), поэтому круговая анимация может продолжаться непрерывно с разумным низким значением. Обратите внимание, что это не является строго необходимым, но легче работать со значениями от 0 до 359 градусов, чем со значениями типа «128000 градусов».

    -
    if (rotateCount > 359) {
    +  
    if (rotateCount > 359) {
       rotateCount %= 360;
     }
  • Затем, под предыдущим блоком, добавьте следующую строку, чтобы вращать spinner: -
    spinner.style.transform = `rotate(${rotateCount}deg)`;
    +
    spinner.style.transform = `rotate(${rotateCount}deg)`;
  • В самом низу внутри функции draw () вставьте следующую строку. Это ключ ко всей операции - вы устанавливаете для переменной, определённой ранее, активный вызов requestAnimation (), который принимает функцию draw () в качестве своего параметра. Это запускает анимацию, постоянно выполняя функцию draw () со скоростью, близкой к 60 FPS.

    -
    rAF = requestAnimationFrame(draw);
    +
    rAF = requestAnimationFrame(draw);
  • Ниже, вызовите функцию draw() для запуска анимации.

    -
    draw();
    +
    draw();
  • @@ -417,7 +417,7 @@ let rAF;

    Просто передайте ему значение, возвращаемое вызовом requestAnimationFrame () для отмены, которое вы сохранили в переменной rAF:

    -
    cancelAnimationFrame(rAF);
    +
    cancelAnimationFrame(rAF);

    Активное обучение: запуск и остановка нашей анимации

    @@ -444,7 +444,7 @@ let rAF;

    В этом примере вы должны анимировать как положение персонажа на экране, так и отображаемый спрайт. В анимации спрайта всего 6 кадров. Если бы вы показывали разные кадры спрайта для каждого кадра, отображаемого на экране, с помощью requestAnimationFrame (), Guybrush двигал бы конечностями слишком быстро, и анимация выглядела бы нелепо. Следовательно, в этом примере регулируется скорость, с которой спрайт циклически повторяет свои кадры, используя следующий код:

    -
    if (posX % 13 === 0) {
    +
    if (posX % 13 === 0) {
       if (sprite === 5) {
         sprite = 0;
       } else {
    @@ -456,7 +456,7 @@ let rAF;
     
     

    ... Фактически, это примерно каждые 6,5 кадров, поскольку мы обновляем posX (положение персонажа на экране) на два кадра:

    -
    if (posX > width/2) {
    +
    if (posX > width/2) {
       newStartPos = -( (width/2) + 102 );
       posX = Math.ceil(newStartPos / 13) * 13;
       console.log(posX);
    @@ -485,7 +485,7 @@ let rAF;
      
  • Внутри пустого элемента {{htmlelement("script")}} на вашей странице, начните с добавления следующих строк кода, которые определяют некоторые переменные и константы, которые вам понадобятся в дальнейшем:

    -
    const spinner = document.querySelector('.spinner p');
    +  
    const spinner = document.querySelector('.spinner p');
     const spinnerContainer = document.querySelector('.spinner');
     let rotateCount = 0;
     let startTime = null;
    @@ -508,7 +508,7 @@ const result = document.querySelector('.result');
  • Ниже добавьте следующую функцию. Она просто берёт два числа и возвращает случайное число между ними. Это понадобится вам позже, чтобы сгенерировать случайный интервал ожидания.

    -
    function random(min,max) {
    +  
    function random(min,max) {
       var num = Math.floor(Math.random()*(max-min)) + min;
       return num;
     }
    @@ -516,7 +516,7 @@ const result = document.querySelector('.result');
  • Затем добавьте функцию draw(), которая анимирует спиннер. Это очень похоже на версию из предыдущего примера простого счётчика:

    -
    function draw(timestamp) {
    +  
    function draw(timestamp) {
       if(!startTime) {
        startTime = timestamp;
       }
    @@ -534,13 +534,13 @@ const result = document.querySelector('.result');
  • Теперь пришло время настроить начальное состояние приложения при первой загрузке страницы. Добавьте следующие две строки, которые просто скрывают абзац результатов и контейнер счётчика с помощью display: none ;.

    -
    result.style.display = 'none';
    +  
    result.style.display = 'none';
     spinnerContainer.style.display = 'none';
  • Затем определите функцию reset (), которая возвращает приложение в исходное состояние, необходимое для повторного запуска игры после её завершения. Добавьте в конец кода следующее:

    -
    function reset() {
    +  
    function reset() {
       btn.style.display = 'block';
       result.textContent = '';
       result.style.display = 'none';
    @@ -549,7 +549,7 @@ spinnerContainer.style.display = 'none';
  • Хорошо, хватит подготовки! Пришло время сделать игру доступной! Добавьте в свой код следующий блок. Функция start () вызывает draw (), чтобы запустить вращение спиннера и отобразить его в пользовательском интерфейсе, скрыть кнопку Start, чтобы вы не могли испортить игру, запустив её несколько раз одновременно, и запускает вызов setTimeout (), который выполняется функция setEndgame () по прошествии случайного интервала от 5 до 10 секунд. Следующий блок также добавляет обработчик событий к вашей кнопке для запуска функции start () при её нажатии.

    -
    btn.addEventListener('click', start);
    +  
    btn.addEventListener('click', start);
     
     function start() {
       draw();
    @@ -569,7 +569,7 @@ function start() {
      
  • Добавьте в свой код следующую функцию:

    -
    function setEndgame() {
    +  
    function setEndgame() {
       cancelAnimationFrame(rAF);
       spinnerContainer.style.display = 'none';
       result.style.display = 'block';
    diff --git a/files/ru/learn/javascript/building_blocks/conditionals/index.html b/files/ru/learn/javascript/building_blocks/conditionals/index.html
    index 6f0b70c1bf..868702ca03 100644
    --- a/files/ru/learn/javascript/building_blocks/conditionals/index.html
    +++ b/files/ru/learn/javascript/building_blocks/conditionals/index.html
    @@ -46,7 +46,7 @@ translation_of: Learn/JavaScript/Building_blocks/conditionals
     
     

    Базовый if...else синтаксис выглядит как {{glossary("pseudocode")}}:

    -
    if (condition) {
    +
    if (condition) {
       code to run if condition is true
     } else {
       run some other code instead
    @@ -66,7 +66,7 @@ translation_of: Learn/JavaScript/Building_blocks/conditionals
     
     

    Стоит заметить, что  else и второй блок скобок { } не обязателен — следующий код так же будет работать:

    -
    if (condition) {
    +
    if (condition) {
       код, который должен выполнить, если условие истина
     }
     
    @@ -76,7 +76,7 @@ translation_of: Learn/JavaScript/Building_blocks/conditionals
     
     

    И, наконец, иногда вы можете встретить код if...else без фигурных скобок в сокращённой форме:

    -
    if (condition) code to run if condition is true
    +
    if (condition) code to run if condition is true
     else run some other code instead

    Это абсолютно рабочий код, но он менее читаем, лучше использовать фигурные скобки, новые строки и отступы.

    @@ -85,7 +85,7 @@ else run some other code instead

    Чтобы лучше понять синтаксис, давайте рассмотрим реальный пример. Представьте, что мать или отец попросили помочь с работой по дому своего ребёнка.  Родитель может сказать: "Если ты поможешь мне с покупками, то я дам тебе дополнительные деньги на карманные расходы, которые ты сможешь потратить на игрушку, какую захочешь".  В JavaScript, мы можем представить это так: 

    -
    var shoppingDone = false;
    +
    var shoppingDone = false;
     
     if (shoppingDone === true) {
       var childsAllowance = 10;
    @@ -105,7 +105,7 @@ if (shoppingDone === true) {
     
     

    Существует способ привязать дополнительные варианты/результаты к вашему if...else — использоватьelse if. Для каждого дополнительного выбора требуется дополнительный блок, который нужно расположить между if() { ... } и else { ... } — проверьте следующий более сложный пример, который может быть частью простого приложения прогноза погоды:

    -
    <label for="weather">Выберите тип погоды сегодня: </label>
    +
    <label for="weather">Выберите тип погоды сегодня: </label>
     <select id="weather">
       <option value="">--Сделайте выбор--</option>
       <option value="sunny">Солнечно</option>
    @@ -116,7 +116,7 @@ if (shoppingDone === true) {
     
     <p></p>
    -
    var select = document.querySelector('select');
    +
    var select = document.querySelector('select');
     var para = document.querySelector('p');
     
     select.addEventListener('change', setWeather);
    @@ -168,7 +168,7 @@ function setWeather() {
     
     

    Мы хотели бы особо обратить внимание на проверку булевых значений (true/false),  и общий шаблон, который вы будете встречать снова и снова. Любое значение, которое не есть  false, undefined, null, 0, NaN, или пустая строка ('') фактически возвращает true при тестировании как условного оператора. Поэтому вы можете просто использовать имя собственной переменной, чтобы проверить, равна ли она true, или существует (т. е. переменная не равна undefined). Например:

    -
    var cheese = 'Cheddar';
    +
    var cheese = 'Cheddar';
     
     if (cheese) {
       console.log('Ура! Есть сыр для приготовления бутерброда.');
    @@ -178,7 +178,7 @@ if (cheese) {
     
     

    И, возвращаясь к нашему предыдущему примеру о ребёнке, выполняющем поручение своего родителя, вы можете это записать так:

    -
    var shoppingDone = false;
    +
    var shoppingDone = false;
     
     if (shoppingDone) { // не нужно явно указывать '=== true'
       var childsAllowance = 10;
    @@ -190,7 +190,7 @@ if (shoppingDone) { // не нужно явно указывать '=== true'
     
     

    Вполне нормально использовать один условный оператор if...else внутри другого — вложить их. Например, мы могли бы обновить наше приложение прогноза погоды, чтобы показать ещё один набор вариантов в зависимости от температуры:

    -
    if (choice === 'sunny') {
    +
    if (choice === 'sunny') {
       if (temperature < 86) {
         para.textContent = 'Сейчас ' + temperature + ' градусов по фаренгейту — хорошо и солнечно. Идите на пляж, или в парк, и купите мороженое.';
       } else if (temperature >= 86) {
    @@ -211,7 +211,7 @@ if (shoppingDone) { // не нужно явно указывать '=== true'
     
     

    Чтобы дать вам пример оператора И, предыдущий фрагмент кода можно переписать так:

    -
    if (choice === 'sunny' && temperature < 86) {
    +
    if (choice === 'sunny' && temperature < 86) {
       para.textContent = 'Сейчас ' + temperature + ' градусов по фаренгейту — хорошо и солнечно. Идите на пляж, или в парк, и купите мороженое.';
     } else if (choice === 'sunny' && temperature >= 86) {
       para.textContent = 'Сейчас ' + temperature + ' градусов по фаренгейту — Жара! Если вы хотите выйти на улицу, обязательно используйте солнцезащитный крем.';
    @@ -221,7 +221,7 @@ if (shoppingDone) { // не нужно явно указывать '=== true'
     
     

    Давайте посмотрим на быстрый пример оператора ИЛИ:

    -
    if (iceCreamVanOutside || houseStatus === 'в огне') {
    +
    if (iceCreamVanOutside || houseStatus === 'в огне') {
       //если подъехал фургон с мороженым или дом горит
       console.log('Вы должны быстро покинуть дом.');
     } else {
    @@ -230,7 +230,7 @@ if (shoppingDone) { // не нужно явно указывать '=== true'
     
     

    Последний тип логического оператора НЕ, выраженный ! оператором, можно использовать для отрицания выражения. Давайте объединим его с ИЛИ в приведённом выше примере:

    -
    if (!(iceCreamVanOutside || houseStatus === 'on fire')) {
    +
    if (!(iceCreamVanOutside || houseStatus === 'on fire')) {
       console.log('Вероятно, можно в нем оставаться.');
     } else {
       console.log('Вы должны быстро покинуть дом.');
    @@ -240,19 +240,19 @@ if (shoppingDone) { // не нужно явно указывать '=== true'
     
     

    Можно сочетать любое количество логических операторов, в любой последовательности и в любой комбинации. В следующем примере код в блоке будет выполняться только в том случае, если оба условия с ИЛИ возвращают true, а следовательно, и оператор И возвращает true:

    -
    if ((x === 5 || y > 3 || z <= 10) && (loggedIn || userName === 'Steve')) {
    +
    if ((x === 5 || y > 3 || z <= 10) && (loggedIn || userName === 'Steve')) {
       // код выполняется
     }

    Распространённой ошибкой при использовании логического оператора ИЛИ в условном выражении является указание переменной, значение которой нужно проверить со списком возможных значений этой переменной, разделённых операторами || (ИЛИ). Например.

    -
    if (x === 5 || 7 || 10 || 20) {
    +
    if (x === 5 || 7 || 10 || 20) {
       // выполнить код
     }

    В данном примере условие в if(...)  всегда будет оцениваться как true, поскольку 7 (или любое другое ненулевое значение) всегда будет оцениваться как true. Фактически, это условие гласит «если х равен 5, или 7 является true». Но нам требуется совсем не это. Чтобы достичь нужной цели, придётся выполнять полноценную проверку после каждого оператора ИЛИ:

    -
    if (x === 5 || x === 7 || x === 10 ||x === 20) {
    +
    if (x === 5 || x === 7 || x === 10 ||x === 20) {
       // выполнить код
     }
    @@ -262,7 +262,7 @@ if (shoppingDone) { // не нужно явно указывать '=== true'

    В этом случае нам поможет оператор switch – он принимает одно единственное выражение или значение, а затем просматривает ряд вариантов, пока не найдут вариант, соответствующий этому значению, после чего выполняет код, назначенный этому варианту. Вот пример использования этого оператора:

    -
    switch (выражение) {
    +
    switch (выражение) {
       case choice1:
         выполнить этот код
         break;
    @@ -297,7 +297,7 @@ if (shoppingDone) { // не нужно явно указывать '=== true'
     
     

    Давайте рассмотрим реальный пример — перепишем наше приложение прогноза погоды с использованием оператора switch:

    -
    <label for="weather">Выберите тип погоды сегодня: </label>
    +
    <label for="weather">Выберите тип погоды сегодня: </label>
     <select id="weather">
       <option value="">--Сделайте выбор--</option>
       <option value="sunny">Солнечно</option>
    @@ -308,7 +308,7 @@ if (shoppingDone) { // не нужно явно указывать '=== true'
     
     <p></p>
    -
    var select = document.querySelector('select');
    +
    var select = document.querySelector('select');
     var para = document.querySelector('p');
     
     select.addEventListener('change', setWeather);
    @@ -345,11 +345,11 @@ function setWeather() {
     
     

    Это последний теоретический раздел данной статьи и мы перейдём к практическим упражнениям. Тернарный или условный оператор имеет простой синтаксис: он проверяет условие и возвращает одно значение или выражение, если условие является true, и другое значение/выражение, если условие является false. Часто это очень удобная альтернатива блоку if...else, позволяющая затрачивать меньшие усилия на написание кода, когда имеется всего лишь два варианта, выбираемых на основе условия true/false. Общая схема оператора:

    -
    ( условие) ? выполнить этот код : выполнить этот код вместо первого
    +
    ( условие) ? выполнить этот код : выполнить этот код вместо первого

    Приведём простой пример:

    -
    var greeting = ( isBirthday ) ? 'С днём рождения, г-н Кузнецов! Хорошо вам повеселиться!' : 'Доброе утро, г-н Кузнецов.';
    +
    var greeting = ( isBirthday ) ? 'С днём рождения, г-н Кузнецов! Хорошо вам повеселиться!' : 'Доброе утро, г-н Кузнецов.';

    У нас есть переменная isBirthday , если она true, мы отправляем посетителю поздравление с днём рождения; если нет – выдаём стандартное приветствие.

    @@ -357,7 +357,7 @@ function setWeather() {

    При использовании тернарного оператора не обязательно ограничиваться лишь значениями переменной, можно выполнять функции или строки кода; все, что угодно. В следующем примере показано простое средство выбора темы, задающее внешний вид веб-сайта с помощью тернарного оператора.

    -
    <label for="theme">Выберите тему: </label>
    +
    <label for="theme">Выберите тему: </label>
     <select id="theme">
       <option value="white">Белая</option>
       <option value="black">Чёрная</option>
    @@ -365,7 +365,7 @@ function setWeather() {
     
     <h1>Это мой веб-сайт</h1>
    -
    var select = document.querySelector('select');
    +
    var select = document.querySelector('select');
     var html = document.querySelector('html');
     document.body.style.padding = '10px';
     
    @@ -422,7 +422,7 @@ select.onchange = function() {
     
  • {{domxref("Storage.getItem()")}} метод принимает один параметр - имя элемента данных, который вы хотите получить - и возвращает значение элемента. Теперь введите эти строки в вашу консоль JavaScript:

    -
    var myName = localStorage.getItem('name');
    +  
    var myName = localStorage.getItem('name');
     myName

    После ввода во второй строке вы должны увидеть, что переменная myName теперь содержит значение элемента данных name.

    @@ -111,7 +111,7 @@ myName
  • {{domxref("Storage.removeItem()")}} метод принимает один параметр - имя элемента данных, который вы хотите удалить, - и удаляет этот элемент из веб-хранилища. Введите следующие строки в вашу консоль JavaScript:

    -
    localStorage.removeItem('name');
    +  
    localStorage.removeItem('name');
     var myName = localStorage.getItem('name');
     myName
    @@ -130,7 +130,7 @@ myName
  • Введите эти строки в консоль JavaScript браузера:

    -
    localStorage.setItem('name','Chris');
    +  
    localStorage.setItem('name','Chris');
     var myName = localStorage.getItem('name');
     myName
    @@ -142,7 +142,7 @@ myName
  • Введите следующий код:

    -
    var myName = localStorage.getItem('name');
    +  
    var myName = localStorage.getItem('name');
     myName

    Вы должны увидеть, что значение всё ещё доступно, даже после закрытия / открытия браузера.

    @@ -175,7 +175,7 @@ myName
  • Мы начнём с создания ссылок на все функции HTML, которыми мы должны манипулировать в этом примере - мы создадим их все как константы, поскольку эти ссылки не нужно изменять в жизненном цикле приложения. Добавьте следующие строки в ваш файл JavaScript:

    -
    // create needed constants
    +  
    // create needed constants
     const rememberDiv = document.querySelector('.remember');
     const forgetDiv = document.querySelector('.forget');
     const form = document.querySelector('form');
    @@ -189,7 +189,7 @@ const personalGreeting = document.querySelector('.personal-greeting');
  • Далее нам нужно включить небольшой обработчик событий, чтобы форма фактически не отправляла себя при нажатии кнопки отправки, так как это не то поведение, которое нам нужно. Добавьте этот фрагмент ниже вашего предыдущего кода:

    -
    // Stop the form from submitting when a button is pressed
    +  
    // Stop the form from submitting when a button is pressed
     form.addEventListener('submit', function(e) {
       e.preventDefault();
     });
    @@ -197,7 +197,7 @@ form.addEventListener('submit', function(e) {
  • Теперь нам нужно добавить обработчик событий, функция-обработчик которого будет запускаться при нажатии кнопки «Say hello». В комментариях подробно объясняется, что делает каждый бит, но в сущности здесь мы берём имя, которое пользователь ввёл в поле ввода текста, и сохраняем его в веб-хранилище с помощью setItem(), затем запускаем функцию nameDisplayCheck(), которая будет обрабатывать обновление фактического текста сайта. Добавьте это в конец: 

    -
    // run function when the 'Say hello' button is clicked
    +  
    // run function when the 'Say hello' button is clicked
     submitBtn.addEventListener('click', function() {
       // store the entered name in web storage
       localStorage.setItem('name', nameInput.value);
    @@ -209,7 +209,7 @@ submitBtn.addEventListener('click', function() {
      
  • На этом этапе нам также необходим обработчик событий для запуска функции при нажатии кнопки «Forget» — она будет отображена только после того как кнопка «Say hello» будет нажата (две формы состояния для переключения между ними). В этой функции мы удаляем переменную name из веб-хранилища используя removeItem(), затем снова запускаем nameDisplayCheck() для обновления. Добавьте этот код в конец:

    -
    // run function when the 'Forget' button is clicked
    +  
    // run function when the 'Forget' button is clicked
     forgetBtn.addEventListener('click', function() {
       // Remove the stored name from web storage
       localStorage.removeItem('name');
    @@ -221,7 +221,7 @@ forgetBtn.addEventListener('click', function() {
      
  • Самое время для определения самой функции nameDisplayCheck(). Здесь мы проверяем была ли переменная name сохранена в веб-хранилище с помощью localStorage.getItem('name') в качестве условия. Если переменная name была сохранена, то вызов вернёт - true; если же нет, то - false. Если true, мы показываем персональное приветствие, отображаем кнопку «Forget», и скрываем кнопку «Say hello». Если же false, мы отображаем общее приветствие и делаем обратное. Опять же, добавьте следующий код в конец:

    -
    // define the nameDisplayCheck() function
    +  
    // define the nameDisplayCheck() function
     function nameDisplayCheck() {
       // check whether the 'name' data item is stored in web Storage
       if(localStorage.getItem('name')) {
    @@ -245,7 +245,7 @@ function nameDisplayCheck() {
      
  • Последнее но не менее важное, нам необходимо запускать функцию nameDisplayCheck() при каждой загрузке страницы. Если мы не сделаем этого, персональное приветствие не будет сохранятся после перезагрузки страницы. Добавьте следующий фрагмент в конец вашего кода:

    -
    document.body.onload = nameDisplayCheck;
    +
    document.body.onload = nameDisplayCheck;
  • @@ -291,7 +291,7 @@ function nameDisplayCheck() {
  • Below the constant declarations, add the following lines:

    -
    // Create an instance of a db object for us to store the open database in
    +  
    // Create an instance of a db object for us to store the open database in
     let db;

    Here we are declaring a variable called db — this will later be used to store an object representing our database. We will use this in a few places, so we've declared it globally here to make things easier.

    @@ -299,7 +299,7 @@ let db;
  • Next, add the following to the bottom of your code:

    -
    window.onload = function() {
    +  
    window.onload = function() {
     
     };
    @@ -308,7 +308,7 @@ let db;
  • Inside the window.onload handler, add the following:

    -
    // Open our database; it is created if it doesn't already exist
    +  
    // Open our database; it is created if it doesn't already exist
     // (see onupgradeneeded below)
     let request = window.indexedDB.open('notes', 1);
    @@ -323,7 +323,7 @@ let request = window.indexedDB.open('notes', 1);
  • Now add the following event handlers just below your previous addition — again inside the window.onload handler:

    -
    // onerror handler signifies that the database didn't open successfully
    +  
    // onerror handler signifies that the database didn't open successfully
     request.onerror = function() {
       console.log('Database failed to open');
     };
    @@ -346,7 +346,7 @@ request.onsuccess = function() {
      
  • Finally for this section, we'll add probably the most important event handler for setting up the database: {{domxref("IDBOpenDBRequest.onupgradeneeded", "request.onupdateneeded")}}. This handler runs if the database has not already been set up, or if the database is opened with a bigger version number than the existing stored database (when performing an upgrade). Add the following code, below your previous handler:

    -
    // Setup the database tables if this has not already been done
    +  
    // Setup the database tables if this has not already been done
     request.onupgradeneeded = function(e) {
       // Grab a reference to the opened database
       let db = e.target.result;
    @@ -372,7 +372,7 @@ request.onupgradeneeded = function(e) {
     
     

    So with this simple database schema set up, when we start adding records to the database each one will be represented as an object along these lines:

    -
    {
    +
    {
       title: "Buy milk",
       body: "Need both cows milk and soya.",
       id: 8
    @@ -384,12 +384,12 @@ request.onupgradeneeded = function(e) {
     
     

    Below your previous event handler (but still inside the window.onload handler), add the following line, which sets up an onsubmit handler that runs a function called addData() when the form is submitted (when the submit {{htmlelement("button")}} is pressed leading to a successful form submission):

    -
    // Create an onsubmit handler so that when the form is submitted the addData() function is run
    +
    // Create an onsubmit handler so that when the form is submitted the addData() function is run
     form.onsubmit = addData;

    Now let's define the addData() function. Add this below your previous line:

    -
    // Define the addData() function
    +
    // Define the addData() function
     function addData(e) {
       // prevent default - we don't want the form to submit in the conventional way
       e.preventDefault();
    @@ -439,7 +439,7 @@ function addData(e) {
     
     

    We've referenced displayData() twice in our code already, so we'd probably better define it. Add this to your code, below the previous function definition:

    -
    // Define the displayData() function
    +
    // Define the displayData() function
     function displayData() {
       // Here we empty the contents of the list element each time the display is updated
       // If you ddn't do this, you'd get duplicates listed each time a new note is added
    @@ -516,7 +516,7 @@ function displayData() {
     
     

    As stated above, when a note's delete button is pressed, the note is deleted. This is achieved by the deleteItem() function, which looks like so:

    -
    // Define the deleteItem() function
    +
    // Define the deleteItem() function
     function deleteItem(e) {
       // retrieve the name of the task we want to delete. We need
       // to convert it to a number before trying it use it with IDB; IDB key
    @@ -566,7 +566,7 @@ function deleteItem(e) {
      
  • For this simple example, we've stored the names of the videos to fetch in an array of objects:

    -
    const videos = [
    +  
    const videos = [
       { 'name' : 'crystal' },
       { 'name' : 'elf' },
       { 'name' : 'frog' },
    @@ -580,7 +580,7 @@ function deleteItem(e) {
     
       

    If each video is found in the database (easily checked by seeing whether request.result evaluates to true — if the record is not present, it will be undefined), its video files (stored as blobs) and the video name are passed straight to the displayVideo() function to place them in the UI. If not, the video name is passed to the fetchVideoFromNetwork() function to ... you guessed it — fetch the video from the network.

    -
    function init() {
    +  
    function init() {
       // Loop through the video names one by one
       for(let i = 0; i < videos.length; i++) {
         // Open transaction, get object store, and get() each video by name
    @@ -607,7 +607,7 @@ function deleteItem(e) {
     
       

    When all those promises have fulfilled, the all() promise fulfills with an array containing all the individual fulfillment values. Inside the all() block, you can see that we then call the displayVideo() function like we did before to display the videos in the UI, then we also call the storeVideo() function to store those videos inside the database.

    -
    let mp4Blob = fetch('videos/' + video.name + '.mp4').then(response =>
    +  
    let mp4Blob = fetch('videos/' + video.name + '.mp4').then(response =>
       response.blob()
     );
     let webmBlob = fetch('videos/' + video.name + '.webm').then(response =>
    @@ -625,7 +625,7 @@ Promise.all([mp4Blob, webmBlob]).then(function(values) {
      
  • Let's look at storeVideo() first. This is very similar to the pattern you saw in the previous example for adding data to the database — we open a readwrite transaction and get an object store reference our videos, create an object representing the record to add to the database, then simply add it using {{domxref("IDBObjectStore.add()")}}.

    -
    function storeVideo(mp4Blob, webmBlob, name) {
    +  
    function storeVideo(mp4Blob, webmBlob, name) {
       // Open transaction, get object store; make it a readwrite so we can write to the IDB
       let objectStore = db.transaction(['videos'], 'readwrite').objectStore('videos');
       // Create a record to add to the IDB
    @@ -645,7 +645,7 @@ Promise.all([mp4Blob, webmBlob]).then(function(values) {
      
  • Last but not least, we have displayVideo(), which creates the DOM elements needed to insert the video in the UI and then appends them to the page. The most interesting parts of this are those shown below — to actually display our video blobs in a <video> element, we need to create object URLs (internal URLs that point to the video blobs stored in memory) using the {{domxref("URL.createObjectURL()")}} method. Once that is done, we can set the object URLs to be the vaues of our {{htmlelement("source")}} element's src attributes, and it works fine.

    -
    function displayVideo(mp4Blob, webmBlob, title) {
    +  
    function displayVideo(mp4Blob, webmBlob, title) {
       // Create object URLs out of the blobs
       let mp4URL = URL.createObjectURL(mp4Blob);
       let webmURL = URL.createObjectURL(webmBlob);
    @@ -694,7 +694,7 @@ Promise.all([mp4Blob, webmBlob]).then(function(values) {
     
     

    Первое, что нужно заметить, это дополнительный кусок кода, расположенный в основном JavaScript файле (см. index.js). Первое,что мы делаем, это проверка на то, что serviceWorker доступен в объекте {{domxref("Navigator")}}. Если этот так, тогда мы знаем, что как минимум, базовые функции сервис-воркера доступны. Внутри проверки мы используем метод {{domxref("ServiceWorkerContainer.register()")}} для регистрации сервис-воркера, находящегося в файле sw.js на текущем источнике, таким образом, он может управлять страницами в текущей или внутренних директориях. Когда промис выполнится, сервис-воркер считается зарегистрированным.

    -
      // Регистрация сервис-воркера для обеспечения доступности сайта в офлайне
    +
      // Регистрация сервис-воркера для обеспечения доступности сайта в офлайне
     
       if('serviceWorker' in navigator) {
         navigator.serviceWorker
    @@ -716,7 +716,7 @@ Promise.all([mp4Blob, webmBlob]).then(function(values) {
     
     

    Здесь мы видим Cache API в действии. Мы используем метод {{domxref("CacheStorage.open()")}} для открытия нового объекта кеша, в котором ответы могут быть сохранены (похоже на объект хранилища IndexedDB). Промис выполнится с объектом {{domxref("Cache")}}, представляющим собой кеш video-store . Затем мы используем метод {{domxref("Cache.addAll()")}} для получения ресурсов и добавления ответов в кеш.

    -
    self.addEventListener('install', function(e) {
    +
    self.addEventListener('install', function(e) {
      e.waitUntil(
        caches.open('video-store').then(function(cache) {
          return cache.addAll([
    @@ -743,7 +743,7 @@ Promise.all([mp4Blob, webmBlob]).then(function(values) {
     
     

    Если совпадение нашлось, то просто возвращаем его как особый ответ. В противном случае, используем fetch() для запроса ресурса из сети.

    -
    self.addEventListener('fetch', function(e) {
    +
    self.addEventListener('fetch', function(e) {
       console.log(e.request.url);
       e.respondWith(
         caches.match(e.request).then(function(response) {
    diff --git a/files/ru/learn/javascript/client-side_web_apis/introduction/index.html b/files/ru/learn/javascript/client-side_web_apis/introduction/index.html
    index 32cf39bfb3..da08302bc6 100644
    --- a/files/ru/learn/javascript/client-side_web_apis/introduction/index.html
    +++ b/files/ru/learn/javascript/client-side_web_apis/introduction/index.html
    @@ -116,7 +116,7 @@ translation_of: Learn/JavaScript/Client-side_web_APIs/Introduction
     
     

    Так как же эти объекты взаимодействуют? Если вы посмотрите на наш пример maps-example.html (see it live also), вы увидите следующий код:

    -
    navigator.geolocation.getCurrentPosition(function(position) {
    +
    navigator.geolocation.getCurrentPosition(function(position) {
       var latlng = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
       var myOptions = {
         zoom: 8,
    @@ -133,11 +133,11 @@ translation_of: Learn/JavaScript/Client-side_web_APIs/Introduction
     
     

    Во-первых, мы хотим использовать метод {{domxref("Geolocation.getCurrentPosition()")}}, чтобы получить текущее положение нашего устройства. Доступ к объекту браузера {{domxref("Geolocation")}} производится с помощью свойства {{domxref("Navigator.geolocation")}}, так что мы начнём с

    -
    navigator.geolocation.getCurrentPosition(function(position) { ... });
    +
    navigator.geolocation.getCurrentPosition(function(position) { ... });

    Это эквивалентно следующему коду

    -
    var myGeo = navigator.geolocation;
    +
    var myGeo = navigator.geolocation;
     myGeo.getCurrentPosition(function(position) { ... });

    Но мы можем использовать точки, чтобы связать доступ к свойствам/методам объекта в одно выражение, уменьшая количество строк в программе.

    @@ -150,22 +150,22 @@ myGeo.getCurrentPosition(function(position) { ... });

    Такой подход, при котором функция вызывается только тогда, когда операция была завершена, очень распространён в JavaScript API — убедиться, что операция была завершена прежде, чем пытаться использовать данные, которые она возвращает, в другой операции. Такие операции также называют асинхронными операциями (asynchronous operations). Учитывая, что получение данных геолокации производится из внешнего устройства (GPS-устройства или другого устройства геолокации), мы не можем быть уверены, что операция считывания будет завершена вовремя и мы сможем незамедлительно использовать возвращаемые ею данные. Поэтому такой код не будет работать:

    -
    var position = navigator.geolocation.getCurrentPosition();
    +
    var position = navigator.geolocation.getCurrentPosition();
     var myLatitude = position.coords.latitude;

    Если первая строка ещё не вернула результат, вторая вызовет ошибку из-за того, что данные геолокации ещё не стали доступны. По этой причине, API, использующие асинхронные операции, разрабатываются с использованием {{glossary("callback function")}}, или более современной системы промисов, которая появилась в ECMAScript 6 и широко используются в новых API.

    Мы совмещаем API Геолокации со сторонним API - Google Maps API, который используем для того, чтобы отметить расположение, возвращаемое  getCurrentPosition() , на Google Map. Чтобы Google Maps API стал доступен на нашей странице, мы включаем его в HTML документ:

    -
    <script type="text/javascript" src="https://maps.google.com/maps/api/js?key=AIzaSyDDuGt0E5IEGkcE6ZfrKfUtE9Ko_de66pA"></script>
    +
    <script type="text/javascript" src="https://maps.google.com/maps/api/js?key=AIzaSyDDuGt0E5IEGkcE6ZfrKfUtE9Ko_de66pA"></script>

    Чтобы использовать этот API, во-первых создадим объект LatLng с помощью конструктора google.maps.LatLng() , принимающим данные геолокации {{domxref("Coordinates.latitude")}} и {{domxref("Coordinates.longitude")}} :

    -
    var latlng = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
    +
    var latlng = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);

    Этот объект сам является значением свойства center объекта настроек (options), который мы назвали myOptions. Затем мы создаём экземпляр объекта, представляющего нашу карту, вызывая конструктор google.maps.Map() и передавая ему два параметра — ссылку на элемент {{htmlelement("div")}}, на котором мы хотим отрисовывать карту (с ID map_canvas), и объект настроек (options), который мы определили выше.

    -
    var myOptions = {
    +
    var myOptions = {
       zoom: 8,
       center: latlng,
       mapTypeId: google.maps.MapTypeId.TERRAIN,
    @@ -193,19 +193,19 @@ var map = new google.maps.Map(document.querySelector("#map_canvas"), myOptions);
     
     

    Найти точку входа Document Object Model (DOM) API ещё проще — при применении этого API используется объект {{domxref("Document")}}, или экземпляр элемента HTML, с которым вы хотите каким-либо образом взаимодействовать, к примеру:

    -
    var em = document.createElement('em'); // создаёт новый элемент em
    +
    var em = document.createElement('em'); // создаёт новый элемент em
     var para = document.querySelector('p'); // ссылка на существующий элемент p
     em.textContent = 'Hello there!'; // присвоение текстового содержимого
     para.appendChild(em); // встроить em внутрь para

    Точки входа других API немного сложнее, часто подразумевается создание особого контекста, в котором будет написан код API. Например, объект контекста Canvas API создаётся получением ссылки на элемент {{htmlelement("canvas")}}, на котором вы хотите рисовать, а затем необходимо вызвать метод {{domxref("HTMLCanvasElement.getContext()")}}:

    -
    var canvas = document.querySelector('canvas');
    +
    var canvas = document.querySelector('canvas');
     var ctx = canvas.getContext('2d');

    Всё, что мы хотим сделать с canvas после этого, достигается вызовом свойств и методов объекта содержимого (content) (который является экземпляром {{domxref("CanvasRenderingContext2D")}}), например:

    -
    Ball.prototype.draw = function() {
    +
    Ball.prototype.draw = function() {
       ctx.beginPath();
       ctx.fillStyle = this.color;
       ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
    @@ -224,7 +224,7 @@ var ctx = canvas.getContext('2d');

    Следующий код содержит простой пример использования событий:

    -
    var requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';
    +
    var requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';
     var request = new XMLHttpRequest();
     request.open('GET', requestURL);
     request.responseType = 'json';
    diff --git a/files/ru/learn/javascript/client-side_web_apis/manipulating_documents/index.html b/files/ru/learn/javascript/client-side_web_apis/manipulating_documents/index.html
    index 9c45929f87..61d208d98f 100644
    --- a/files/ru/learn/javascript/client-side_web_apis/manipulating_documents/index.html
    +++ b/files/ru/learn/javascript/client-side_web_apis/manipulating_documents/index.html
    @@ -51,7 +51,7 @@ translation_of: Learn/JavaScript/Client-side_web_APIs/Manipulating_documents
     
     

    Мы создали простую страницу примера в dom-example.html (см. также live). Попробуйте открыть это в своём браузере - это очень простая страница, содержащая элемент {{htmlelement("section")}}, внутри которого вы можете найти изображение и абзац со ссылкой внутри. Исходный код HTML выглядит так:

    -
    <!DOCTYPE html>
    +
    <!DOCTYPE html>
     <html>
       <head>
         <meta charset="utf-8">
    @@ -95,13 +95,13 @@ translation_of: Learn/JavaScript/Client-side_web_APIs/Manipulating_documents
      
  • Возьмите локальную копию страницы dom-example.html page и изображение, которое вместе с ним.
  • Добавьте элемент <script></script> чуть выше закрывающего тега </body>.
  • Чтобы управлять элементом внутри DOM, вам сначала нужно выбрать его и сохранить ссылку на него внутри переменной. Внутри вашего скриптового элемента добавьте следующую строку: -
    var link = document.querySelector('a');
    +
    var link = document.querySelector('a');
  • Теперь у нас есть ссылка на элемент, хранящаяся в переменной, мы можем начать её манипулировать с использованием доступных ему свойств и методов (они определены на таких интерфейсах, как {{domxref("HTMLAnchorElement")}} в случае {{htmlelement ("a")}}, его более общий родительский интерфейс {{domxref ("HTMLElement")}} и {{domxref("Node")}} - который представляет все узлы в DOM). Прежде всего, давайте изменим текст внутри ссылки, обновив значение свойства {{domxref("Node.textContent")}}. Добавьте следующую строку ниже предыдущей: -
    link.textContent = 'Mozilla Developer Network';
    +
    link.textContent = 'Mozilla Developer Network';
  • Мы также должны изменить URL-адрес, на который указывает ссылка, чтобы он не попадал в неправильное место при нажатии. Добавьте следующую строку, опять внизу: -
    link.href = 'https://developer.mozilla.org';
    +
    link.href = 'https://developer.mozilla.org';
  • @@ -124,20 +124,20 @@ translation_of: Learn/JavaScript/Client-side_web_APIs/Manipulating_documents
    1. Возвращаясь к текущему примеру, давайте начнём с захвата ссылки на наш элемент {{htmlelement("section")}} - добавьте следующий код внизу существующего скрипта (сделайте то же самое с другими строками): -
      var sect = document.querySelector('section');
      +
      var sect = document.querySelector('section');
    2. Теперь давайте создадим новый абзац, используя {{domxref("Document.createElement()")}} и передадим ему текстовое содержимое так же, как и раньше: -
      var para = document.createElement('p');
      +  
      var para = document.createElement('p');
       para.textContent = 'We hope you enjoyed the ride.';
    3. Теперь вы можете добавить новый абзац в конце раздела, используя {{domxref("Node.appendChild()")}}: -
      sect.appendChild(para);
      +
      sect.appendChild(para);
    4. Наконец, для этой части, давайте добавим текстовый узел в абзац, где находится ссылка, чтобы оформить предложение красиво. Сначала мы создадим текстовый узел, используя {{domxref("Document.createTextNode()")}}: -
      var text = document.createTextNode(' — the premier source for web development knowledge.');
      +
      var text = document.createTextNode(' — the premier source for web development knowledge.');
    5. Теперь мы возьмём ссылку на абзац, в котором находится ссылка, и добавим к нему текстовый узел: -
      var linkPara = document.querySelector('p');
      +  
      var linkPara = document.querySelector('p');
       linkPara.appendChild(text);
    @@ -150,17 +150,17 @@ linkPara.appendChild(text);

    Если бы мы хотели переместить абзац со ссылкой внутри него в нижней части раздела, мы могли бы просто сделать это:

    -
    sect.appendChild(linkPara);
    +
    sect.appendChild(linkPara);

    Это переводит абзац вниз в нижнюю часть раздела. Вы могли подумать, что это сделает вторую копию, но это не так - linkPara - ссылка на единственную копию этого абзаца. Если вы хотите сделать копию и добавить её также, вам нужно будет использовать {{domxref("Node.cloneNode()")}}.

    Удаление узла довольно просто, по крайней мере, когда у вас есть ссылка на удаляемый узел и его родительский элемент. В нашем случае мы просто используем {{domxref("Node.removeChild()")}}, например:

    -
    sect.removeChild(linkPara);
    +
    sect.removeChild(linkPara);

    Он становится немного сложнее, если вы хотите удалить узел, основанный только на ссылке на себя, что довольно распространено. Нет способа сообщить узлу удалить себя, поэтому вам нужно будет сделать следующее.

    -
    linkPara.parentNode.removeChild(linkPara);
    +
    linkPara.parentNode.removeChild(linkPara);

    Попробуйте добавить вышеуказанные строки в свой код.

    @@ -174,14 +174,14 @@ linkPara.appendChild(text);
    1. В качестве примера попробуйте добавить эти строки в наш текущий пример: -
      para.style.color = 'white';
      +  
      para.style.color = 'white';
       para.style.backgroundColor = 'black';
       para.style.padding = '10px';
       para.style.width = '250px';
       para.style.textAlign = 'center';
    2. Перезагрузите страницу, и вы увидите, что стили были применены к абзацу. Если вы посмотрите на этот параграф в инспекторе Page Inspector/DOM inspector вашего браузера, вы увидите, что эти строки действительно добавляют встроенные стили в документ: -
      <p style="color: white; background-color: black; padding: 10px; width: 250px; text-align: center;">We hope you enjoyed the ride.</p>
      +
      <p style="color: white; background-color: black; padding: 10px; width: 250px; text-align: center;">We hope you enjoyed the ride.</p>
    @@ -194,7 +194,7 @@ para.style.textAlign = 'center';
    1. Удалите предыдущие пять строк, добавленных в JavaScript.
    2. Добавьте в свой HTML-код следующее: {{htmlelement("head")}}: -
      <style>
      +  
      <style>
       .highlight {
         color: white;
         background-color: black;
      @@ -205,7 +205,7 @@ para.style.textAlign = 'center';
      </style>
    3. Теперь мы перейдём к очень полезному методу для общего манипулирования HTML - {{domxref("Element.setAttribute()")}} - это принимает два аргумента, атрибут, который вы хотите установить для элемента, и значение, которое вы хотите для его установки. В этом случае мы укажем имя класса выделения в нашем абзаце: -
      para.setAttribute('class', 'highlight');
      +
      para.setAttribute('class', 'highlight');
    4. Обновите свою страницу, и вы не увидите изменений - CSS по-прежнему применяется к абзацу, но на этот раз, предоставив ему класс, который выбран нашим правилом CSS, а не как встроенные стили CSS.
    @@ -230,17 +230,17 @@ para.style.textAlign = 'center';
    1. Прежде всего, давайте возьмём ссылку на div, а затем возьмём ширину и высоту окна просмотра (внутреннее окно, где отображается ваш документ) и сохраните их в переменных - эти два значения удобно содержатся в {{domxref("Window.innerWidth")}} и {{domxref("Window.innerHeight")}}. Добавьте следующие строки внутри существующего элемента {{htmlelement("script")}}: -
      var div = document.querySelector('div');
      +  
      var div = document.querySelector('div');
       var WIDTH = window.innerWidth;
       var HEIGHT = window.innerHeight;
    2. Затем мы динамически изменяем ширину и высоту div, равную ширине окна просмотра. Добавьте следующие две строки ниже своих первых: -
      div.style.width = WIDTH + 'px';
      +  
      div.style.width = WIDTH + 'px';
       div.style.height = HEIGHT + 'px';
    3. Сохраните и попробуйте обновить браузер - теперь вы должны увидеть, что div становится таким же большим, как ваш видовой экран, независимо от того, какой размер экрана вы используете. Если теперь вы попытаетесь изменить размер окна, чтобы увеличить его, вы увидите, что div остаётся одного размера - мы устанавливаем его только один раз.
    4. Как насчёт того, чтобы мы использовали событие, чтобы размер div изменялся при изменении размера окна? Объект {{domxref("Window")}} имеет событие, имеющееся на нем с именем resize, которое запускается каждый раз при изменении размера окна - давайте обратимся к нему через обработчик событий {{domxref("Window.onresize")}} и повторяйте наш размерный код каждый раз, когда он изменяется. Добавьте нижеследующую часть кода: -
      window.onresize = function() {
      +  
      window.onresize = function() {
         WIDTH = window.innerWidth;
         HEIGHT = window.innerHeight;
         div.style.width = WIDTH + 'px';
      diff --git a/files/ru/learn/javascript/first_steps/a_first_splash/index.html b/files/ru/learn/javascript/first_steps/a_first_splash/index.html
      index 6da71e0814..e6a210e0d5 100644
      --- a/files/ru/learn/javascript/first_steps/a_first_splash/index.html
      +++ b/files/ru/learn/javascript/first_steps/a_first_splash/index.html
      @@ -49,7 +49,7 @@ original_slug: Learn/JavaScript/Первые_шаги/A_first_splash
       
       
      -
      for (var i = 1 ; i < 21 ; i++) { console.log(i) }
      +
      for (var i = 1 ; i < 21 ; i++) { console.log(i) }

      Что случилось? Номера с 1 по 20 были напечатаны в консоли. Это из-за цикла. Цикл for принимает три входных значения (аргументы):
      Начальное значение: в этом случае мы начинаем подсчёт c 1, но это может быть любое число которое вам нравится. Вы можете заменить i любым другим именем, которое вам нравится, но я использую его как условность, потому что оно короткое и легко запоминается. Условие выхода: Здесь мы указали i <21 - цикл будет продолжаться до тех пор, пока i будет меньше 21. Когда i достигнет 21, цикл больше не будет работать. Инкремент: мы указали i ++, что означает «увеличить i на 1». Цикл будет выполняться один раз для каждого значения i, пока оно не достигнет значения 21 (как обсуждалось выше). В этом случае мы просто печатаем значение i в консоли на каждой итерации с помощью {{domxref ("Console.log", "console.log ()")}}.

      Теперь давайте посмотрим на цикл в нашей игре угадывания чисел - в функции resetGame () можно найти следующее:

      -
      var resetParas = document.querySelectorAll('.resultParas p');
      +
      var resetParas = document.querySelectorAll('.resultParas p');
       for (var i = 0 ; i < resetParas.length ; i++) {
         resetParas[i].textContent = '';
       }
      @@ -625,7 +625,7 @@ for (var i = 0 ; i < resetParas.length ; i++) {

      Давайте добавим ещё одно окончательное улучшение, прежде чем перейти к обсуждению. Добавьте следующую строку чуть ниже var resetButton; в верхней части вашего JavaScript, затем сохраните файл:

      -
      guessField.focus();
      +
      guessField.focus();

      Эта строка использует метод {{domxref("HTMLElement.focus", "focus()")}}, чтобы автоматически помещать текстовый курсор в текстовое поле {{htmlelement("input")}}, как только загрузится страница. Пользователь сможет сразу набрать свою первую догадку, не нажимая поле формы. Это всего лишь небольшое дополнение, но оно улучшает удобство использования - даёт пользователю хорошую визуальную подсказку относительно того, что они должны делать в игре.

      @@ -633,13 +633,13 @@ for (var i = 0 ; i < resetParas.length ; i++) {

      В нашем примере мы сначала создали переменную guessField, которая запоминает значение из поля ввода в нашем HTML - следующая строка находится среди первых в нашем коде:

      -
      var guessField = document.querySelector('.guessField');
      +
      var guessField = document.querySelector('.guessField');

      Чтобы получить это значение, мы использовали метод {{domxref("document.querySelector", "querySelector()")}} объекта {{domxref("document")}}. querySelector() "берет" одну часть информации -  CSS selector, который выбирает нужный элемент.

      Поскольку guessField теперь содержит ссылку на элемент {{htmlelement("input")}}, теперь он будет иметь доступ к ряду свойств (в основном к переменным, хранящимся внутри объектов, некоторые значения которых нельзя изменять) и методы (в основном функции, хранящиеся внутри объектов). Одним из методов, доступных для ввода элементов, является focus (), поэтому мы можем теперь использовать эту строку для фокусировки ввода текста:

      -
      guessField.focus();
      +
      guessField.focus();

      Для переменных, которые не содержат ссылок на элементы формы, не будет доступен focus(). Например, переменная guesses содержит ссылку на элемент {{htmlelement ("p")}}, а guessCount содержит число.

      @@ -652,17 +652,17 @@ for (var i = 0 ; i < resetParas.length ; i++) {
    5. Далее, откройте инструменты разработчика в вашем браузере, и убедитесь, что вы перешли во вкладку с консолью JavaScript.
    6. Введите guessField и консоль покажет, что переменная содержит элемент {{htmlelement("input")}}. Вы также можете заметить, что консоль автоматически заполняет имена объектов, которые существуют внутри исполняющей среды, включая ваши переменные!
    7. Теперь введите следующее: -
      guessField.value = 'Hello';
      +
      guessField.value = 'Hello';
      Свойство value представляет текущее значение, введённое в текстовое поле. Заметьте, что, введя эту команду, мы изменили его!
    8. Попробуйте ввести guesses и нажать return. Консоль покажет, что в переменной содержится элемент {{htmlelement("p")}}.
    9. Теперь попробуйте ввести: -
      guesses.value
      +
      guesses.value
      Браузер вернёт вам undefined, потому что value не существует в параграфах.
    10. Для изменения текста внутри параграфа, взамен используйте свойство {{domxref("Node.textContent", "textContent")}}. Попробуйте: -
      guesses.textContent = 'Where is my paragraph?';
      +
      guesses.textContent = 'Where is my paragraph?';
    11. Теперь немного повеселимся. Попробуйте ввести следующие строки, одну за другой: -
      guesses.style.backgroundColor = 'yellow';
      +  
      guesses.style.backgroundColor = 'yellow';
       guesses.style.fontSize = '200%';
       guesses.style.padding = '10px';
       guesses.style.boxShadow = '3px 3px 6px black';
      diff --git a/files/ru/learn/javascript/first_steps/silly_story_generator/index.html b/files/ru/learn/javascript/first_steps/silly_story_generator/index.html index 042b6e844d..2cfbea95b2 100644 --- a/files/ru/learn/javascript/first_steps/silly_story_generator/index.html +++ b/files/ru/learn/javascript/first_steps/silly_story_generator/index.html @@ -125,7 +125,7 @@ original_slug: Learn/JavaScript/Первые_шаги/Создатель_глу
      • Вам не нужно каким-либо образом редактировать HTML, кроме как применять JavaScript к вашему HTML.
      • Если вы не уверены, правильно ли применяется JavaScript для вашего HTML-кода, попробуйте временно удалить все остальное из файла JavaScript, добавив в него простой кусочек JavaScript, который, как вы знаете, создаст очевидный эффект, а затем сохраните и обновите. Следующий, например, делает фон элемента {{htmlelement ("html")}} красного цвета - поэтому все окно браузера должно быть красным, если JavaScript применяется правильно: -
        document.querySelector('html').style.backgroundColor = 'red';
        +
        document.querySelector('html').style.backgroundColor = 'red';
      • Math.round() - это встроенный метод JavaScript, который просто округляет результат вычисления до ближайшего целого числа.
      diff --git a/files/ru/learn/javascript/first_steps/strings/index.html b/files/ru/learn/javascript/first_steps/strings/index.html index 9acead263a..b63ccbcc82 100644 --- a/files/ru/learn/javascript/first_steps/strings/index.html +++ b/files/ru/learn/javascript/first_steps/strings/index.html @@ -37,17 +37,17 @@ original_slug: Learn/JavaScript/Первые_шаги/Строки
      1. Для начала введите следующие строки: -
        var string = 'The revolution will not be televised.';
        +  
        var string = 'The revolution will not be televised.';
         string;
      2. Как и в случае с числами, мы объявляем переменную, инициализируя её строковым значением, а затем возвращаем значение. Единственное различие здесь в том, что при написании строки вам нужно окружить значение кавычками. 
      3. Если вы не сделаете этого или пропустите одну из кавычек, вы получите сообщение об ошибке. Попробуйте ввести следующие строки: -
        var badString = This is a test;
        +  
        var badString = This is a test;
         var badString = 'This is a test;
         var badString = This is a test';
        Эти строки не работают, потому что любая текстовая строка без кавычек считается именем переменной, именем свойства, зарезервированным словом или чем-то подобным. Если браузер не может найти его, возникает ошибка (например, «missing, before statement»). Если браузер может видеть, где начинается строка, но не может найти конец строки, как указано во 2-й строке, она жалуется на ошибку (с «unterminated string literal»). Если ваша программа выявляет такие ошибки, вернитесь назад и проверьте все свои строки, чтобы убедиться, что у вас нет пропущенных кавычек.
      4. Следующий код будет выполнен только в том случае, если ранее была объявлена переменная string — убедитесь сами: -
        var badString = string;
        +  
        var badString = string;
         badString;
        В настоящее время строка badString имеет то же значение, что и строка string.
      @@ -56,22 +56,22 @@ badString;
      1. В JavaScript вы можете выбрать одинарные кавычки или двойные кавычки, чтобы обернуть ваши строки. Оба варианта будут работать нормально: -
        var sgl = 'Single quotes.';
        +  
        var sgl = 'Single quotes.';
         var dbl = "Double quotes";
         sgl;
         dbl;
      2. Существует очень мало различий между одиночными и двойными кавычками, и решение какие из них использовать в коде остаётся на ваше усмотрение. Однако вы должны выбрать один вариант и придерживаться его, иначе ваш код может выдать ошибку, особенно если вы используете разные кавычки в одной строке! Ниже приведён пример: -
        var badQuotes = 'What on earth?";
        +
        var badQuotes = 'What on earth?";
      3. Браузер будет считать, что строка не была закрыта, потому что в строке может появиться другой тип цитаты, который вы не используете, чтобы хранить ваши строки в переменных. Из примера можно понять, о чем идёт речь (в коде ошибок нет): -
        var sglDbl = 'Would you eat a "fish supper"?';
        +  
        var sglDbl = 'Would you eat a "fish supper"?';
         var dblSgl = "I'm feeling blue.";
         sglDbl;
         dblSgl;
      4. Однако вы не можете включить один и тот же знак кавычки внутри строки, если он используется для их хранения. Ниже приведена ошибка, браузер ошибочно определяет место, где строка кончается: -
        var bigmouth = 'I've got no right to take my place...';
        +
        var bigmouth = 'I've got no right to take my place...';
        Что приводит нас к следующей теме.
      @@ -79,7 +79,7 @@ dblSgl;
    12. Чтобы исправить нашу предыдущую строку кода, нам нужно дать понять браузеру, что кавычка в середине строки не является меткой её конца. Экранирование символов означает, что мы делаем что-то с ними, чтобы убедиться, что они распознаются как текст, а не часть кода. В JavaScript мы делаем это, помещая обратную косую черту непосредственно перед символом. Введите эти строки:

      -
      var bigmouth = 'I\'ve got no right to take my place...';
      +
      var bigmouth = 'I\'ve got no right to take my place...';
       bigmouth;

      Так лучше. Таким же образом можно экранировать и другие символы, например "\. Кроме того существуют специальные коды. Для дополнительной информации см. Escape notation.

      @@ -89,17 +89,17 @@ bigmouth;
      1. Конкатенация — это новомодное программистское слово, которое означает «объединить». Объединение строк в JavaScript использует оператор плюс (+), тот же, который мы используем для сложения чисел, но в этом контексте он делает кое-что другое. Попробуем пример в нашей консоли.
      2. -
        var one = 'Hello, ';
        +  
        var one = 'Hello, ';
         var two = 'how are you?';
         var joined = one + two;
         joined;
        Результат этой программы - это переменная joined, содержащая значение "Hello, how are you?".
      3. В последнем случае мы просто объединим две строки вместе, но на самом деле, вы можете объединить столько строк, сколько хотите, до тех пор, пока вы ставите + между ними. Попробуйте это: -
        var multiple = one + one + one + one + two;
        +  
        var multiple = one + one + one + one + two;
         multiple;
      4. Вы также можете использовать сочетание переменных и фактических строк. Попробуйте это: -
        var response = one + 'I am fine — ' + two;
        +  
        var response = one + 'I am fine — ' + two;
         response;
      @@ -112,9 +112,9 @@ response;

      Давайте посмотрим на конкатенацию строк в действии — вот пример из предыдущего курса:

      -
      <button>Press me</button>
      +
      <button>Press me</button>
      -
      var button = document.querySelector('button');
      +
      var button = document.querySelector('button');
       
       button.onclick = function() {
         var name = prompt('What is your name?');
      @@ -129,22 +129,22 @@ button.onclick = function() {
       
       
      1. Итак, что происходит, когда мы пытаемся добавить (или конкатенировать) строку и число? Попробуем это в нашей консоли: -
        'Front ' + 242;
        +  
        'Front ' + 242;
         
        Вы можете ожидать, что это вызовет ошибку, но все работает отлично. Попытка представить строку как число на самом деле не имеет смысла, но число как строку — имеет, поэтому браузер довольно умно преобразует число в строку и объединяет две строки вместе.
      2. Вы даже можете сделать это с двумя числами, вы можете заставить число стать строкой, обернув её в кавычки. Попробуйте следующее (мы используем оператор typeof для того, чтобы установить является ли переменная числом или строкой): -
        var myDate = '19' + '67';
        +  
        var myDate = '19' + '67';
         typeof myDate;
      3. Если у вас есть числовая переменная, которую вы хотите преобразовать в строчную без внесения каких-либо иных изменений или строковую переменную, которую вы хотите преобразовать в число, вы можете использовать следующие две конструкции:
        • Объект {{jsxref ("Number")}} преобразует всё переданное в него в число, если это возможно. Попробуйте следующее: -
          var myString = '123';
          +    
          var myString = '123';
           var myNum = Number(myString);
           typeof myNum;
        • С другой стороны, каждое число имеет метод, называемый toString(), который преобразует его в эквивалентную строку. Попробуй это: -
          var myNum = 123;
          +    
          var myNum = 123;
           var myString = myNum.toString();
           typeof myString;
        • diff --git a/files/ru/learn/javascript/first_steps/useful_string_methods/index.html b/files/ru/learn/javascript/first_steps/useful_string_methods/index.html index 722895282b..90450169e7 100644 --- a/files/ru/learn/javascript/first_steps/useful_string_methods/index.html +++ b/files/ru/learn/javascript/first_steps/useful_string_methods/index.html @@ -39,7 +39,7 @@ original_slug: Learn/JavaScript/Первые_шаги/Useful_string_methods

          Почти всё в JavaScript является объектами. Когда вы создаёте строку, например: 

          -
          let string = 'This is my string';
          +
          let string = 'This is my string';

          ваша переменная становится строковым объектом, и, как результат, ей доступно множество свойств и методов. Можете убедиться в этом, перейдя на страницу {{jsxref ("String")}} и просмотрев на ней список свойств и методов!

          @@ -51,7 +51,7 @@ original_slug: Learn/JavaScript/Первые_шаги/Useful_string_methods

          Это легко — вы просто используете свойство {{jsxref ("String.prototype.length", "length")}}. Попробуйте ввести следующие строки:

          -
          let browserType = 'mozilla';
          +
          let browserType = 'mozilla';
           browserType.length;

          Результатом должно быть число 7, потому что слово «mozilla» состоит из 7 символов. Это свойство можно применить, например, если вы захотите найти длины серии имён, чтобы их можно было отображать по порядку длины или сообщить пользователю, что имя пользователя, которое он ввёл в поле формы, слишком длинное, если оно превышает определённую длину.

          @@ -60,11 +60,11 @@ browserType.length;

          Вы можете вернуть любой символ внутри строки, используя обозначение в квадратных скобках. Это означает, что вы добавляете квадратные скобки ([ ]) в конце вашего имени переменной. В квадратных скобках вы указываете номер символа, который хотите вернуть. Например, чтобы получить первую букву, нужно написать:

          -
          browserType[0];
          +
          browserType[0];

          Компьютеры считают от 0, а не 1! Чтобы получить последний символ любой строки, мы могли бы использовать следующую строку, объединив эту технику с свойством length:

          -
           browserType[browserType.length-1];
          +
           browserType[browserType.length-1];

          Длина слова «mozilla» равна 7, но, поскольку счёт начинается с 0, позиция последнего символа равна 6, поэтому нам нужна length-1. Такой способ можно использовать, чтобы найти первую букву ряда строк и упорядочить их по алфавиту.

          @@ -72,17 +72,17 @@ browserType.length;
      1. Иногда вам может понадобиться выяснить, присутствует ли меньшая строка внутри большей (обычно мы говорим, что внутри строки есть подстрока). Это можно сделать с помощью метода {{jsxref ("String.prototype.indexOf ()", "indexOf ()")}}, который принимает одну {{glossary ("parameter")}} - подстроку, которую вы хотите найти. Введите: -
        browserType.indexOf('zilla');
        +
        browserType.indexOf('zilla');
        Это даёт нам результат 2, потому что подстрока «zilla» начинается в позиции 2 ("m" — 0, "o" — 1, "z" — 2) внутри «mozilla». Такой код можно использовать для фильтрации строк. Например, если есть список веб-адресов и вы хотите распечатать только те, которые содержат «mozilla».
      1. Это можно сделать по-другому, что, возможно, ещё более эффективно. Введите следующее: -
        browserType.indexOf('vanilla');
        +
        browserType.indexOf('vanilla');
        Это должно дать вам результат -1. Такое значение возвращается, когда подстрока, в данном случае «vanilla», не найдена в основной строке.

        Вы можете использовать это, чтобы найти все экземпляры строк, которые не содержат подстроку «mozilla» (для обратного эффекта, используйте оператор отрицания): -
        if(browserType.indexOf('mozilla') === -1) {
        +  
        if(browserType.indexOf('mozilla') === -1) {
           // сделать что-то, если 'mozilla'
           // не является частью этой строки
         }
        @@ -93,10 +93,10 @@ if(browserType.indexOf('mozilla') !== -1) {
         }
      2. Когда вы знаете, где подстрока начинается внутри строки, и вы знаете, на каком символе вы хотите её завершить, можно использовать {{jsxref ("String.prototype.slice ()", "slice ()")}}  для извлечения. Попробуйте следующее: -
        browserType.slice(0,3);
        +
        browserType.slice(0,3);
        Это возвращает «moz». Первым параметром является позиция символа, с которого начинается извлечение, а второй параметр — позиция последнего символа, перед которым нужно отсечь строку. Таким образом, срез происходит с первой позиции, вплоть до последней позиции, но не включая её (помним, что счёт идёт с 0, а не с 1). Также можно сказать, что второй параметр равен длине возвращаемой строки.
      3. Кроме того, если вы знаете, что хотите извлечь все остальные символы в строке после определённого символа, вам не нужно включать второй параметр. Достаточно включить только положение символа, с которого вы хотите начать извлечение оставшихся символов в строке. Введите: -
        browserType.slice(2);
        +
        browserType.slice(2);
        Этот код возвращает «zilla» — это потому, что позиция символа 2 — это буква z, и поскольку вы не указали второй параметр, возвращаемая подстрока состояла из всех остальных символов в строке.
      @@ -110,7 +110,7 @@ if(browserType.indexOf('mozilla') !== -1) {

      Попробуем ввести следующие строки, чтобы узнать, что происходит:

      -
      var radData = 'My NaMe Is MuD';
      +
      var radData = 'My NaMe Is MuD';
       radData.toLowerCase();
       radData.toUpperCase();
      @@ -120,7 +120,7 @@ radData.toUpperCase();

      Он принимает два параметра — строку, которую вы хотите заменить, и строку, которую вы хотите вставить вместо заменяемой. Попробуйте этот пример:

      -
      browserType.replace('moz','van');
      +
      browserType.replace('moz','van');

      Обратите внимание, что для фактического получения обновлённого значения, отражённого в переменной browserType в реальной программе, вам нужно будет установить значение переменной в результате операции; он не просто обновляет значение подстроки автоматически. Таким образом, вы должны были бы написать это: browserType = browserType.replace('moz','van');

      @@ -143,7 +143,7 @@ radData.toUpperCase();