Подготовка к первому собесу
Published: 2022-07-10 14:38:28

---
У меня в четверг 14.07.2022 должен быть первый собес. Сегодня воскресенье, сижу готовлюсь к собесу. Составил некоторый список, по которому нужно пройтись и повторить, а некоторое выучить заново (я не знаю про контекст (`this`) ничего, про promise и т.д.).

## Список тем:

1. Переменные
2. Типы данных
3. Операторы
4. Преобразование типов
5. Циклы
6. Функции
7. Рекурсия и стек
8. Контекст (this)
9. Генераторы, итераторы
10. Fetch
11. Promise
12. async/await
13. Работа с DOM


## 1. Переменные
 Переменная – это «именованное хранилище» для данных. 
Имя переменной должно содержать только буквы, цифры или символы $ и _.
Первый символ не должен быть цифрой.
Существует 2 основных отличия `var` от `let`/`const`:
Переменные `var` не имеют блочной области видимости, они ограничены, как минимум, телом функции.
Объявления (инициализация) переменных `var` производится в начале исполнения функции (или скрипта для глобальных переменных).

## 2. Типы данных
Есть JavaScript 8 основных типов данных:
`Number` `BigInt` `string` `boolean` 
`null` `undefined` `object` `symbol`

Переменная в JavaScript может содержать любые данные. В один момент там может быть строка, а в другой – число.

`number` для любых чисел: целочисленных или чисел с плавающей точкой; целочисленные значения ограничены диапазоном ±(253-1). Кроме обычных чисел, существуют так называемые «специальные числовые значения», которые относятся к этому типу данных: Infinity, -Infinity и NaN.

`bigint` для целых чисел произвольной длины. Чтобы создать значение типа BigInt, необходимо добавить `n` в конец числового литерала.

`string` для строк. Строка может содержать ноль или больше символов, нет отдельного символьного типа.

`boolean` для true/false.

`null` для неизвестных значений – отдельный тип, имеющий одно значение null.

`undefined` для неприсвоенных значений – отдельный тип, имеющий одно значение undefined.

`symbol` для уникальных идентификаторов.

Тип object (`объект`) – особенный. Все остальные типы называются «примитивными», потому что их значениями могут быть только простые значения (будь то строка, или число, или что-то ещё). В объектах же хранят коллекции данных или более сложные структуры.

Оператор **typeof** возвращает тип аргумента. Это полезно, когда мы хотим обрабатывать значения различных типов по-разному или просто хотим сделать проверку.
У него есть две синтаксические формы:
1) Синтаксис оператора: typeof x.
2) Синтаксис функции: typeof (x).

## 3. Операторы
Есть 3 основных вида операторов:

1. Базовые (либо математические)
2. Операторы сравнения
3. Логические операторы

_Математические операторы_ в зависимости от применения могут быть двух типов: унарные и бинарные, отличаются от кол-ва операндов, к которым они применяются. Операнд (аргумент) - это то, к чему применяется оператор. Унарный оператор (-800) один операнд. "+" складывает и преобразовывает строки, остальные операторы могут только выполнять арифметические действия, то есть преобразуют все операнды в числа ("25" - 5 = 20 (тип данных Number). Применяя унарный оператор "+" к строке, имеющую цифру (например "25"), оператор преобразует строку в число, то есть + "25" (тип данных `Number`).

_Логические операторы_: цепочка ИЛИ (`||`) возвращает первое истинное значение или последнее, если такое значение не найдено.
 И (`&&`) возвращает первое ложное значение. Или последнее, если ничего не найдено. Вышеуказанные правила схожи с поведением ИЛИ. Разница в том, что И возвращает первое ложное значение, а ИЛИ –  первое истинное. Приоритет оператора `&&` больше, чем у `||`. 
Оператор НЕ (`!`) сначала приводит аргумент к логическому типу true/false, затем возвращает противоположное значение.

Все _операторы сравнения_ возвращают значение логического типа (true или false)

## 4. Преобразование типов
Существует 3 наиболее широко используемых преобразования: строковое, численное и логическое.
_Строковое_ – Происходит, когда нам нужно что-то вывести. Может быть вызвано с помощью `String(value)`. Для примитивных значений работает очевидным образом.
_Численное_ – Происходит в математических операциях. Может быть вызвано с помощью `Number(value)`:
`undefined` => `NaN`
`null` =>	`0`
`true / false` =>	`1 / 0`
`string` => `Пробельные символы по краям обрезаются. Далее, если остаётся пустая строка, то получаем 0, иначе из непустой строки «считывается» число. При ошибке результат NaN`.
_Логическое_ – Происходит в логических операциях. Может быть вызвано с помощью `Boolean(value)`:
`0, null, undefined, NaN, ""` => `false`
`любое другое значение` => `true`
Большую часть из этих правил легко понять и запомнить. Особые случаи, в которых часто допускаются ошибки:
`undefined` при численном преобразовании становится `NaN`, не `0`.
`"0"` и строки из одних пробелов типа `" "` при логическом преобразовании всегда `true`.

## 5. Циклы
Циклы - простой способ сделать какое-то действие несколько раз. 
Цикл **`for`**  повторяет действия, пока не произойдёт какое-либо специальное событие завершения цикла.
```
for ([начало]; [условие]; [шаг]) выражения
```
Цикл **`do...while`** повторяется пока заданное условие истинно.

```
do
  выражения
while (условие);
```

_Пример_:
В следующем примере, цикл `do` выполнится минимум 1 раз и запускается снова, пока i меньше 5.
```
do {
  i += 1;
  console.log(i);
} while (i < 5);
```
Цикл **`while`** выполняет выражения пока условие истинно. Выглядит он так:

```
while (условие)
  выражения
```
Метка (**`label`**) представляет собой оператор с идентификатором, который позволяет вам ссылаться на какое-то место в вашей программе. Например, вы можете использовать метку, чтобы обозначить цикл, а затем использовать операторы `break` или `continue`, чтобы указать, должна ли программа прерывать цикл или продолжать его выполнение:
```
метка :
   оператор
```
В этом примере, метка `markLoop` обозначает цикл `while`.

```
markLoop:
while (theMark == true) {
   doSomething();
}
```
Используйте оператор **`break`**, чтобы прерывать цикл, переключать управление или в сочетании с оператором `Label`. Синтаксис оператора может быть таким:
1) _break_;
2) _break Label_;
Оператор **`continue`** используется, чтобы шагнуть на шаг вперёд в циклах `while`, `do-while`, `for` или перейти к `метке`. Синтаксис continue может выглядеть так:
1) _continue_;
2) _continue Метка_;

Оператор **`for...in`** проходит по всем перечислимым свойствам объекта. JavaScript выполнит указанные выражения для каждого отдельного свойства:

```
for (variable in object) {
  выражения
}
```
## 6. Функции
_**Создание функции:**_
_Объявление функции_ (**Function Declaration**) по синтаксису является инструкцией (statement) и состоит из следующих частей:

```
function square(number) {
  return number * number;
}
```
Существует ещё один синтаксис создания функций, который называется **Function Expression** (_Функциональное Выражение_):

```
let sayHi = square(number) {
  return number * number;
};
```
Функции вида "`function expression`" удобны, когда функция передаётся аргументом другой функции.

Отличия **Function Expression** в сравнении с **Function Declaration**

Во-первых, синтаксис: как определить, что есть что в коде.

- Function Declaration: функция объявляется отдельной конструкцией «function…» в основном потоке кода:

```
function sum(a, b) {
  return a + b;
}
```
- Function Expression: функция, созданная внутри другого выражения или синтаксической конструкции. В данном случае функция создаётся в правой части «выражения присваивания» =:


```
let sum = function(a, b) {
  return a + b;
};
```
Более тонкое отличие состоит, в том, когда создаётся функция движком JavaScript.

**Function Expression** создаётся, когда выполнение **_доходит до него_**, и затем уже _может использоваться_.

После того, как поток выполнения достигнет правой части выражения присваивания let sum = function… – с этого момента, функция считается созданной и может быть использована (присвоена переменной, вызвана и т.д. ).

С _Function Declaration_ всё иначе.

**Function Declaration _можно использовать во всем скрипте_** (или блоке кода, если функция объявлена в блоке).

Другими словами, когда движок JavaScript готовится выполнять скрипт или блок кода, прежде всего он ищет в нём _Function Declaration_ и создаёт все такие функции. Можно считать этот процесс «стадией инициализации».
И только после того, как все объявления _Function Declaration_ будут обработаны, продолжится выполнение.
В результате, функции, созданные, как _Function Declaration_ могут быть вызваны раньше своих определений.

**Метод** — _это функция, которая является свойством объекта_.

## 7. Рекурсия и стек
Функция может вызывать саму себя. Три способа такого вызова:

1) по имени функции
2) arguments.callee
3) по переменной, которая ссылается на функцию

Функция, которая вызывает саму себя, называется **рекурсивной функцией** (recursive function). Получается, что рекурсия аналогична циклу (loop). Оба вызывают некоторый код несколько раз, и оба требуют условия (чтобы избежать бесконечного цикла, вернее бесконечной рекурсии). Информация о процессе выполнения запущенной функции хранится в её контексте выполнения (_execution context_). _**Контекст выполнения**_ – специальная внутренняя структура данных, которая содержит информацию о вызове функции

## 8. Контекст (`this`)
Значение `this` – это объект «перед точкой», который использовался для вызова метода.
Функции, которые находятся в объекте в качестве его свойств, называются «методами».
Методы позволяют объектам «действовать»: `object.doSomething()`.
Методы _могут ссылаться на объект_ через `this`.
Значение `this` определяется во время _исполнения_ кода.

При объявлении любой функции в ней можно использовать `this`, но этот `this` не имеет значения до тех пор, пока функция не будет вызвана.
Эта функция может быть скопирована между объектами (из одного объекта в другой).
Когда функция вызывается синтаксисом «метода» – `object.method()`, значением `this` во время вызова является объект перед точкой.
Также, заметим, что стрелочные функции являются _особенными_ – у них нет `this`. Когда внутри стрелочной функции обращаются к `this`, то его значение берётся снаружи.

## 9. Генераторы, итераторы
_**Итераторы**_
Объект является итератором, если он умеет обращаться к элементам коллекции по одному за раз, при этом отслеживая своё текущее положение внутри этой последовательности. В JavaScript итератор - это объект, который предоставляет метод `next()`, возвращающий следующий элемент последовательности. Этот метод возвращает объект с двумя свойствами: done и value.

После создания, объект-итератор может быть явно использован, с помощью вызовов метода `next()`.

_**Генераторы**_
_Генераторы используют для создания итераторов_.
В то время как пользовательские итераторы могут быть весьма полезны, при их программировании требуется уделять серьёзное внимание поддержке внутреннего состояния. Генераторы предоставляют мощную альтернативу: они позволяют определить алгоритм перебора, написав единственную функцию, которая умеет поддерживать собственное состояние.

Генераторы - это специальный тип функции, который работает как фабрика итераторов. Функция становится генератором, если содержит один или более `yield` операторов и использует `function*` синтаксис.

## 10. Fetch

Fetch API предоставляет интерфейс JavaScript для работы с запросами и ответами HTTP. Он также предоставляет глобальный метод `fetch()`, который позволяет легко и логично получать ресурсы по сети асинхронно.

## 11. Promise

Объект `Promise` используется для отложенных и асинхронных вычислений. Promise – это специальный объект, который содержит своё состояние. Вначале pending («ожидание»), затем – одно из: fulfilled («выполнено успешно») или rejected («выполнено с ошибкой»).

*Синтаксис**
```
new Promise(executor);
new Promise(function(resolve, reject) { ... });
```

Пример:
```
// Создаётся объект promise
let promise = new Promise((resolve, reject) => {

  setTimeout(() => {
    // переведёт промис в состояние fulfilled с результатом "result"
    resolve("result");
  }, 1000);

});

// promise.then навешивает обработчики на успешный результат или ошибку
promise
  .then(
    result => {
      // первая функция-обработчик - запустится при вызове resolve
      alert("Fulfilled: " + result); // result - аргумент resolve
    },
    error => {
      // вторая функция - запустится при вызове reject
      alert("Rejected: " + error); // error - аргумент reject
    }
  );
```
Конечно, вместо setTimeout внутри функции промиса может быть и запрос к серверу и ожидание ввода пользователя, или другой асинхронный процесс. Главное, чтобы по своему завершению он вызвал resolve или reject, которые передадут результат обработчикам.

## 12. async/await
Объявление `async function` определяет асинхронную функцию, которая возвращает объект `AsyncFunction`.

После вызова функция async возвращает `Promise`. Когда результат был получен, Promise завершается, возвращая полученное значение.  Когда функция `async` выбрасывает исключение, `Promise` ответит отказом с выброшенным (`throws`) значением.

Функция `async` может содержать выражение `await`, которое приостанавливает выполнение функции `async` и ожидает ответа от переданного `Promise`, затем возобновляя выполнение функции `async` и возвращая полученное значение.

Ключевое слово `await` допустимо только в асинхронных функциях. В другом контексте вы получите ошибку `SyntaxError`.

Цель функций `async/await` упростить использование promises синхронно и воспроизвести некоторое действие над группой  Promises. Точно так же как Promises подобны структурированным колбэкам, `async/await` подобна комбинации генераторов и promises.
**Пример:**
```
async function add1(x) {
  const a = await resolveAfter2Seconds(20);
  const b = await resolveAfter2Seconds(30);
  return x + a + b;
}
```

## 13. Работа с DOM

Основой HTML-документа являются теги.
В соответствии с объектной моделью документа («Document Object Model», коротко DOM), каждый HTML-тег является объектом. Вложенные теги являются «детьми» родительского элемента. Текст, который находится внутри тега, также является объектом.

Все эти объекты доступны при помощи JavaScript, мы можем использовать их для изменения страницы.