02OperationsExpressionsTypesComparisonConditionLogic.md 25 KB

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

Алфавит

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

Словарь

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

Ключевые слова

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

Идентификаторы

Переменные, имена функций - это идентификаторы. Вы можете их создавать сами. Каждый идентификатор начинается с буквы, $ или _. Со второго символа так же допускается использование цифр:

var a15               = 15;
var camelCaseVariable = "Для отделения слов в идентификаторах можно использовать большие буквы";
var underscore_variable = "или подчерки";
const PI              = Math.PI;

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

JS - Case Sensitive.

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

var a = 5;
VAR b = 10;

Присвоение

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

var1 = value1;

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

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

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

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

var a = 5;
a     = a +1;

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

;

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

a = 5; b = a + 5;

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

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

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

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

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

Девочка в шоке

Числа.

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

var b = 5
var c = 6.57
const myPi = Math.PI

В JS для целых и дробных существует единый тип Number. Так же этот тип имеет специальные значения NaN (Not A Number), +Infinity и -Infinity (бесконечность).

4/"asdf" // бессмысленное выражение, как результат - NaN
15/0 // на ноль делить нельзя, но в высшей математике - можно :-)

Восьмеричные и двоичные литералы (ES6)

console.log(0b1010)
console.log(0777)
console.log(0o555)
console.log(0xFF)

Основные операции над числами:

  • Сложение
  • Вычитание
  • Умножение
  • Деление
  • Остаток от деления %
Сокращенные формы: операции и присвоение:
var b  = 5;
    b += 2;

var a  = 5;
    a %= 2;

Поэксперементируйте и объясните, что происходит в примере выше, а так же как выглядит не сокращенная форма операций выше.

Инкремент и декремент

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

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

Math

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

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 ( для чисел с дробной частью )

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

Boolean

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

В основном используется для двух задач:

  • Та или иная переменная-флаг для внутреннего использования. Например isLoggedIn может показывать залогинен пользователь на сайте или нет:
var isLoggedIn = true
var isLoggedIn = false
  • Как результат той или иной логической операции:
var isLoggedIn = (password == rightPassword) && (login == rightLogin) //пользователь залогинен, если пароль и логин совпадают с верными
var isUserOldEnoughToSeeTheAdultVideos = age > 18 // пользователь может смотреть видео, если ему больше 18 лет.

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

Array

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

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

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

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

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

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

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

person["name"]
person.surname

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

undefined

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

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

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

null

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

typeof

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

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

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

Равенство

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 приводит к числу, а потом сравнивает два числа:
false == "0"

Больше, меньше...

5 > 6
6 > 5
5.0 >= 5
"a" < "b"
"b" <= "a"

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

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

if else

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

Синтаксис:

if (cond){
    //if cond is true
}
else {
    //if cond is false
}

Например:

var age = prompt("Сколько вам лет?","");
if (+age < 18){
    alert("Рано вам еще");
}
else {
    alert("Смотрите на здоровье");
}

{}

Код, заключенный в фигурные скобки называется блоком кода. В зависимости от условия, он выполняется или невыполняется последовательно и целиком. Таким образом, фигурные скобки указывают интерпретатору, где начинается и где заканчивается блок кода для выполнения или не выполнения. Так же в блоке кода могут быть свои локальные переменные, определенные с помощью let (ES6).

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

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

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

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


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

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

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

Ставьте фигурные скобки всегда, и избавите себя от лишней траты времени на отладку :-)

if может быть так же применен без else:

var answer = confirm("будешь кексик?");
if (answer){
    alert("кушай на здоровье");
}
alert("пока");
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("то ли киборг, то ли ошибка"); 
}

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

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

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

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

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

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

switch

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

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

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" будут работать так же как и ранее. Замечание: в силу особенностей реализации запуска кода со страницы, пара примеров выше не работают без копипасты в консоль.

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

Триединость приведения типов

Не !

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

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

Или ||

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

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

И &&

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

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 как результат выражения.

confirm('a') || confirm('b')

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

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

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;

Запятая

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

var a = (Math.random(), Math.PI); // это выражение с запятой
var arr = [1,2,3]; // это массив
var obj = {a: 'b', c: 'd'} // это объект

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

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

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

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

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

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