# Операции, Типы, Сравнение, Условия и Логические операторы.

## Алфавит

Код состоит из спецсимволов `~!$%^&*()-_+=\|/?[]:;,.<>"'`, букв английского алфавита и цифр

### Словарь
'Словарь' языка делится на две основные части:

#### Ключевые слова
Эти слова описаны в стандарте языка, и имеют особый смысл. Например слово `var`. С каждым или почти каждым мы ознакомимся в процессе изучения курса.

#### Идентификаторы
Переменные, имена функций - это идентификаторы. Вы можете их создавать сами. Каждый идентификатор начинается с буквы, `$` или `_`. Со второго символа так же допускается использование цифр:
```javascript
var a15               = 15;
var camelCaseVariable = "Для отделения слов в идентификаторах можно использовать большие буквы";
var underscore_variable = "или подчерки";
```

В **JS** принято использовать **camelCase**.

#### **JS** - **Case Sensitive**.
Это значит, что размер имеет значение. Букв. Т. е. переменные `AaA` и `aAa` это *разные* переменные. Ключевые слова  в **JS** пишутся маленькими буквами, и подсветка это показывает:

```javascript
var a = 5;
VAR b = 10;
```

## Присвоение

Одна из основных операций, без которой не обходится практически ни одна строка кода - операция **присвоения**, т. е. связывания имени переменной с определенным значением:

```javascript
var1 = value1;
```

**Слева** от знака равенства **должна** быть переменная, **справа** - **выражение**.

**Присвоение** происходит по следующему алгоритму:

- Выражение справа *вычисляется*
- *Значение* выражения запоминается где-то в недрах **JS**
- переменная слева связывается со значением.

Таким образом, в программировании имеют смысл бессмысленные с математической точки зрения вещи:

```javascript
var a = 5;
a     = a +1;
```

**Во всех** случаях, кроме присвоения, когда переменная встречается в коде, её значение подставляется в это место как подвыражение, т. е. происходит чтения значения переменной.

## `;`

Во многих языках программирования, каждый **оператор** отделяется от других с помощью символа `;`. Это подсказка интерпретатору или компилятору языка. В **JS** практически всегда можно обойтись без этих символов, однако в некоторых случаях они обязательны, например, если 
несколько операторов находятся в одной строке:

```javascript
a = 5; b = a + 5;
```

Однако *обычно* нет причин для написания операторов в одну строку.

## Типы данных и операции над ними

**Тип данных** - это множество допустимых значений, как было уже упомянуто.

### Операции над данными.

Операции зависят от типа данных, и зачастую имеют смысл для одного типа данных и не имеют его для других. Например нет смысла делить на `Boolean` или дату, однако *иногда* есть смысл делить на строку (если в ней число). С этим бывают определенные сложности.

![Девочка в шоке](http://img1.joyreactor.cc/pics/post/%D0%BA%D0%B0%D1%80%D1%82%D0%B8%D0%BD%D0%BA%D0%B8-javascript-%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-3340155.jpeg "Девочка в шоке")

### Числа.

Вы уже знакомы с числами:

```javascript
var b = 5
var c = 6.57
var myPi = Math.PI
```
В JS для целых и дробных существует единый тип `Number`. Так же этот тип имеет специальные значения `NaN` (Not A Number), `+Infinity` и `-Infinity` (бесконечность).

```javascript
4/"asdf" // бессмысленное выражение, как результат - NaN
```

```javascript
15/0 // на ноль делить нельзя, но в высшей математике - можно :-)
```

#### Основные операции над числами:
- Сложение
- Вычитание
- Умножение
- Деление
- Остаток от деления `%`

##### Сокращенные формы: операции и присвоение:

```javascript
var b  = 5;
    b += 2;

var a  = 5;
    a %= 2;
```
> Поэксперементируйте и объясните, что происходит в примере выше, а так же как выглядит *не* сокращенная форма операций выше.

#### Инкремент и декремент
- Преинкремент (увеличение на 1) `++a`
- Предекремент (уменьшение на 1) `--a`
- Постинкремент (увеличение на 1) `a++`
- Постдекремент (уменьшение на 1) `a--`

> Поэксперементируйте и объясните, в чем разница между пост- и пре- инкрементом и декрементом.

#### `Math`

Множество нужных операций по работе с числами есть в объекте-коллекции `Math`, который является частью стандартной библиотеки:

```javascript
alert(Math.random()); 
var a = 5;
var aBy2 = Math.floor(a/2);
var aModulo =  a % 2;
```
Больше информации о `Math`: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Math

### Строки

Строка - тип `String`. Некое множество символов. Для перевода строки в число используйте `+` или `parseInt` ( для целых ) или `parseFloat` ( для чисел
с дробной частью )

```javascript
var someString = "foo";
var concatenatedString = someString + " bar";
var stringWithNumberInside = "123";
var integerNumberByString  = +stringWithNumberInside;
var floatNumberByString    = parseFloat("-15.15");
```

### Boolean

`true` (правда) или `false` (ложь)

В основном используется для двух задач:
- Та или иная переменная-флаг для внутреннего использования. Например `isLoggedIn` может показывать залогинен пользователь на сайте или нет:

```javascript
var isLoggedIn = true
var isLoggedIn = false
```
- Как результат той или иной логической операции:

```javascript
var isLoggedIn = (password == rightPassword) && (login == rightLogin) //пользователь залогинен, если пароль и логин совпадают с верными
var isUserOldEnoughToSeeTheAdultVideos = age > 18 // пользователь может смотреть видео, если ему больше 18 лет.
```

Логическое выражение может использоваться в условиях, которые делают или не делают определенные операции в зависимости от истинности
условия.

### Array

Сложная структура данных, обращение к элементам которого происходит по целочисленному индексу, начинающемуся с нуля:

```javascript
var a = [0,1,2,3,4];
var squaresOfA = a.map(function(item){
    return item*item;
});
```

Обращение к элементами приосходит с помощью `[]`:

```javascript
alert(a[4]);
alert(squaresOfA[4]);

var cubesOfA = [];


cubesOfA[0] = a[0]*a[0]*a[0];
cubesOfA[1] = a[1]*a[1]*a[1];
cubesOfA[2] = a[2]*a[2]*a[2];
cubesOfA[3] = a[3]*a[3]*a[3];
cubesOfA[4] = a[4]*a[4]*a[4];
```

### Object

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

```javascript
var person = {
    name: "Ivan",
    surname: "Ivanov",
    age: 25
}
```

Доступ к полям происходит через `.` или через `[]` по строковому ключу:

```javascript
person["name"]
person.surname
```

> Сформируйте объект с массивами и массив с объектами с осмысленными данными.

### `undefined`

Если что-то в Javascript не определено, то это, обычно, `undefined`:

```javascript
var a; //значение a - undefined
```

`undefined` - это и тип, и единственное его значение.

### `null`

`null` - в целом аналогичен `undefined`, но предназначен для использования его программистом. Т. е. если вы хотите пометить переменную как *пустую* -
используйте `null`

## `typeof`

позволяет узнать тип в виде строки

## Операции сравнения

Каждое выражение можно сравнивать с другим выражением:

### Равенство
```javascript
1 == 2
1 != 2
1 == 1
1 != 1
"text" == 5
"text" != 5
"text" == "Text"
"text" == "text"
true   == "true"
true   == false
false  == 0
false  === 0
""     == false
""     !== false
```

Равенства деляться на строгие (`===`) и нестрогие (`==`):
- Строгое сравнение сравнивают по **типу** и **значению**.
- Нестрогое сравнение сравнивает по **приведенному** значению. Обычно в таком случае **JS** приводит к числу, а потом сравнивает два числа:

```javascript
false == "0"
```

### Больше, меньше...
```javascript
5 > 6
6 > 5
5.0 >= 5
"a" < "b"
"b" <= "a"
```

Результатом таких выражений является значение типа `Boolean`, то есть `true` или `false`

## Условные операторы


### `if` `else`

Любое значение, которое может быть приведено к типу `Boolean` может стать условием для условного оператора `if-else`:

**Синтаксис:**

```javascript
if (cond){
    //if cond is true
}
else {
    //if cond is false
}
```
**Например:**
```javascript
var age = prompt("Сколько вам лет?","");
if (+age < 18){
    alert("Рано вам еще");
}
else {
    alert("Смотрите на здоровье");
}
```

#### `{}`
Код, заключенный в фигурные скобки называется **блоком кода**. В зависимости от условия, он выполняется или невыполняется *последовательно* и *целиком*. Таким образом, фигурные скобки указывают интерпретатору, где начинается и где заканчивается блок кода для выполнения 
или не выполнения.

#### `if`, Краткие формы, выстрел в ногу и `;` 

```javascript
//если у вас ОДИН оператор в блоке if или else, вы можете не использовать фигурные скобки:

if (+age < 18) alert("Рано вам еще");
else alert("Смотрите на здоровье");

//но учтите: ";" - тоже оператор:


if (+age < 18) alert("Рано вам еще");
else; alert("Смотрите на здоровье");

//эквивалентно:

if (+age < 18) alert("Рано вам еще");
else{
    ;
}
alert("Смотрите на здоровье");
// т.е. последний alert будет срабатывать ВСЕГДА.
```
Ставьте фигурные скобки **всегда**, и избавите себя от лишней траты времени на отладку :-)


`if` может быть так же применен без `else`:
```javascript
var answer = confirm("будешь кексик?");
if (answer){
    alert("кушай на здоровье");
}
alert("пока");
```


```javascript
var age = +prompt("Сколько вам лет?","");
if (age < 18){
    alert("школьник");
}
else if (age > 18 && age < 30){
    alert("молодеж");
}
else if (age > 30 && age < 45){
    alert("зрелость");
}
else if (age > 45 && age < 60){
    alert("закат");
}
else if (age > 60){
    alert("как пенсия?");
}
else {
    alert("то ли киборг, то ли ошибка"); 
}
```

> Добавьте условие отрицательного возраста в пример выше.  Расставьте недостающие (но *синтаксически* необязательные) фигурные скобки. 

```javascript
var str = prompt("Поговори со мной!!!!","");
if (str){
    alert("Ты такой милый " + str);
}
else {
    alert("Козёл!!!!!11");
}
```

### Тернарный оператор

Данный оператор позволяет сократить пару `if-else` в некоторых ситуациях:

```javascript
var text = confirm("Нажмите что-нибудь") ? "Вы нажали Yes" : "Вы нажали No";
alert(text);
var text = confirm("Да, Нет, Наверное") ? "Да" : (confirm ("Нет или Наверное?") ? "Нет" :  "Наверное") // вложенный тернарный оператор
alert(text);
```

**Принципиально отличие** тернарного оператора от `if`-`else` заключается в том, что тернарный оператор является **выражением**.

### `switch`

`switch` позволяет выполнять определенные блоки кода в зависимости от значения выражения:

```javascript
var color = prompt("Введите цвет","");
switch (color){
    case "red": document.write("<div style='background-color: red;'>красный</div>");
                break;
    case "black": document.write("<div style='background-color: black; color: white;'>черный</div>");
                break;
    case "blue": document.write("<div style='background-color: blue;'>синий</div>");
                break;
    case "green": document.write("<div style='background-color: green;'>зеленый</div>");
                break;
    default: document.write("<div style='background-color: gray;'>Я не понял</div>");
}
```

`break` в `switch` обеспечивает переход на конец конструкции `switch` (т. е. на код, следущий за `}`). Если `break` не поставить, то можно объединить
несколько `case` в один:

> Перепишите пример выше, используя `if-else`

```javascript
var color = prompt("Введите цвет","");
switch (color){
    case "red": document.write("<div style='background-color: red;'>красный</div>");
    case "black": document.write("<div style='background-color: black; color: white;'>черный</div>");
                break;
    case "blue": document.write("<div style='background-color: blue;'>синий</div>");
    case "green": document.write("<div style='background-color: green;'>зеленый</div>");
                break;
    default: document.write("<div style='background-color: gray;'>Я не понял</div>");
}
```

В примере выше "red" будет рисовать и "red" и "black", "blue" так же объединится с "green". Однако "black" и "green" будут работать так же как и ранее.
**Замечание**: в силу особенностей реализации запуска кода со страницы, пара примеров выше не работают без копипасты в консоль.

## Логические операторы

#### **Не** `!`

```javascript
5 == 5
5 != 5
!true
!false
!(5 == 5)
!(5 != 5)
!!0
```

Как видите, **не** позволяет инвертировать булево значение. *Двойное не* позволяет получить *приведенное к типу* `Boolean` значение переменной.

#### **Или** `||`

**Или** позволяет объединять несколько булевых значений в одно, по следующей логике: **Если A или B истинно**, то результат - истина. Иначе - результат
ложный:

```javascript
var isDrunk = isDrunkByBeer || isDrunkByVodka //если пили или водку, или пиво, все равно пьяные :-)
var isFlyable = isFly || isBird || isAircraft || isBatman || isSuperman //что-то может летать, если это нечто - самолет, муха или птица, не важно что это.
```

Таблица истинности:

|    A   |   B   |  результат  |
| ------ | ----- | --- |
| false  | false | false |
| **true**  | false | **true** |
| false  | **true** | **true** |
| **true**  | **true** | **true** |

#### **И** `&&`

**И** требует что бы ВСЕ операнды были истинны, иначе результат ложен:

```javascript
var isBodun   = isDrunkByBeer &&  isDrunkByVodka //если пили и водку, и пиво, то бодун :-)
var isYoung   = age > 16 && age < 30 // человек молод от 16 до 30.
```

Таблица истинности:

|    A   |   B   |     |
| ------ | ----- | --- |
| false  | false | false |
| **true**   | false | false |
| false  | **true**  | false |
| **true**   | **true**  | **true**  |

### Порядок выполнения логических выражений

Логические выражения выполняются *оптимальным способом* слева направо. То есть, если в **ИЛИ** попался `true`, то следующая часть выражения даже не
будет обрабатываться, так как результат уже `true`. **ИЛИ** ищет `true`, и, когда находит, экономит ресурсы компьютера, *сразу же* возвращая true как результат выражения.

```javascript
confirm('a') || confirm('b')
```

**И**, напротив, "ищет" `false`. То есть, если найден `false`, то нет смысла далее обрабатывать выражение - оно, так или иначе, будет `false`.

```javascript
confirm('a') && confirm('b')
```

Учтите, что `||` и `&&` возвращают **не** `true` или `false` (значение булевского типа), а значения подвыражения как оно есть:
Как `false` интерпретируются:
- `false` 
- `0` // 0 как число
- `""` //пустая строка
- `null`
- `undefined`
- `NaN`

Как `true` интерпретируются все остальные значения, в том числе:
- `Infinity`
- `-Infinity`
- `"0"` //строка не пуста. однако +"0" уже 0 как число, а значит false
- `{}` //пустой объект - всё равно `true`
- `[]` //пустой массив `[] == false`, но в остальных случаях работает как true

**Для проверки используйте** `!!`, двойное отрицание: `!!null` равен `false`, таким образом мы можем почти всегда проверить как интерпретируется
то или иное значение.

В общем случае объект является `true`, за исключением `null` и `[] == false`

```javascript
2
1+1
2*1
// bool type cast
!!2
!!0
!!1
// or
2 || 1
2 || 0
//and
2 && 1
1 && 2
0 && 2
// or and and difference
0 || 1 || 2
0 && 1 && 2
2 || 1 || 0
2 && 1 && 0
confirm('left') || confirm('right')
confirm('left') && confirm('right')
//null, undefined, so on
null || 2
undefined && 1
alert("Hello") && confirm('Are you sexy?');
alert("Hello") || confirm('Are you drunk?');
//brackets and complex expressions
(undefined || 2) && (2 || 0)
(2 && 1) || (null && 0)
(2 > 1) && "greater"
(2 < 1) && null
null && (2 < 1)
// ternary operator
1 ? "one" : "not one"
0 ? "zero" : "not zero"
"0" ? "\"zero\"" : "not `zero`"
parseInt("0") ? 'true' : 'false'
("" || 2) && (3 || "3.5") || (4 && 5)
(-1 + 1) && "zero"
"-1" + 1 && "oups"
(typeof null === 'object') ? "null is object" : "null is null"
// ternary && ||
Math.random() < 0.5 && 'less' || 'more'
(a = Math.random()) < 0.5 && 'less: '+a || 'more: '+a
//in for array
[2,3,5,7,11].indexOf(7) > -1 ? 'prime' : 'not found'
'random' in Math
'indexOf' in []
var a = b = c = d = 5;
```

## Разделяй и властвуй

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

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

> Напишите бессмысленное выражение, используя максимум усвоенных на текущий момент знаний.

## Пунктуация в коде.

Пунктуация в коде - это отступы. Обычно каждый вложенный **блок кода** должен быть сдвинут вправо на 4 пробела. Современные **IDE** неплохо справляются с этой задачей, так что, скорее всего, просто не мешайте им.