Основы JavaScript
Andrey Gorokhov
Комментарии
Комментарии могут находиться в любом месте программы и никак не влияют на её выполнение.
Однострочные комментарии начинаются с двойного слэша //. Текст считается комментарием до конца строки:
//Команда ниже говорит "Привет"
alert('Привет');
alert('Мир'); //Второе сообщение выводим отдельно
Многострочные комментарии начинаются слешем-звездочкой /* и заканчиваются звездочкой-слэшем */, вот так:
/* Пример с двумя сообщениями.
Это - многострочный комментарий.
*/
alert('Привет');
alert('Мир');
Всё содержимое комментария игнорируется. Если поместить код внутрь /* … */ или после //, то он не выполнится.
/* Закомментировали код
alert('Привет');
*/
alert('Мир');
Вложенные комментарии не поддерживаются! В этом коде будет ошибка:
/*
/* вложенный комментарий ?!? */
*/
alert('Мир');
Переменные
Для объявления создания переменной используется ключевое слово var:
var message;
После объявления можно записать в переменную данные:
var message; message = 'Hello';
Эти данные будут сохранены в соответствующей области памяти и в дальнейшем доступны при обращении по имени:
var message; message = 'Hello!'; alert(message); //Выведет содержимое переменной
Для краткости можно совместить объявление переменной и запись данных:
var message = 'Hello!';
Можно объявить несколько переменных сразу:
var user = 'John', age = 25, message = 'Hello';
Значение в переменной можно изменять сколько угодно раз:
var message; message = 'Hello!'; message = 'World!'; //Заменили значение alert(message);
При изменении значения старое содержимое переменной удаляется.
Можно объявить две переменные и копировать данные из одной в другую:
var hello = 'Hello world!'; var message; // Cкопировали значение message = hello; alert(hello); // Hello world! alert(message); // Hello world!
Имена переменных
На имя переменной в JavaScript наложены всего два ограничения.
- Имя может состоять из: букв, цифр, символов
$и_. - Первый символ не должен быть цифрой.
Шесть типов данных
Число
var n = 123; n = 12.345;
Единый тип число используется как для целых, так и для дробных чисел.
Существуют специальные числовые значения Infinity (бесконечность) и NaN (not a number, ошибка вычислений).
Например, бесконечность Infinity получается при делении на ноль:
alert(1 / 0); // Infinity
Ошибка вычислений NaN будет результатом некорректной математической операции, например:
alert("нечисло" * 2); // NaN
Строка
var str = "Мама мыла раму"; str = 'Одинарные кавычки тоже подойдут';
Булевый (логический) тип «boolean»
У него всего два значения: true (истина) и false (ложь).
Как правило, такой тип используется для хранения значения типа да/нет, например:
var checked = true; // Поле формы помечено галочкой checked = false; // Поле формы не содержит галочки
Значение «null»
Значение null не относится ни к одному из типов выше, а образует свой отдельный тип, состоящий из единственного значения null:
var age = null;
В JavaScript null не является «ссылкой на несуществующий объект» или «нулевым указателем», как в некоторых других языках. Это просто специальное значение, которое имеет смысл «ничего» или «значение неизвестно».
Значение «undefined»
Значение undefined, как и null, образует свой собственный тип, состоящий из одного этого значения. Оно имеет смысл «значение не присвоено».
Если переменная объявлена, но в неё ничего не записано, то её значение как раз и есть undefined:
var x; alert(x); // undefined
Объекты
Первые 5 типов называют «примитивными». Особняком стоит шестой тип: «объекты».
Он используется для коллекций данных и для объявления более сложных сущностей.
Объявляются объекты при помощи фигурных скобок {...}, например:
var user = {name: "Вася"};
Условия
Синтаксис:
if (условие) {
действие;
}
Условие с альтернативным действием:
if (условие) {
действия;
} else {
другие действия;
}
Вложенные условия:
if (условие1) {
if (условие2) {
действия;
}
}
Как работают условия?
Выражение в круглых скобках (проверка) возвращает true или false. Действие внутри условия выполняется, если вернулось true. Если выражение вернуло false, действие не выполнится.
Код внутри проверок
Операторы сравнения:

Операторы равенства:

Логические операторы:
- Оператор
&&или «логическое И» возвращаетtrueтолько в том случае, если оба условия слева и справа от него возвращаютtrue. - Оператор
||или «логическое ИЛИ» возвращаетtrue, если любое из условий слева или справа от него возвращаетtrue. - Оператор
!или «логическое отрицание» меняет булево значение выражения справа от него на противоположное.
Циклы
Цикл for
Синтаксис:
for (var i = 0; i < 10; i++) {
console.log(i) // 0 1 2 3 4 5 6 7 8 9
}
var i = 0; — подготовительная часть, исходное значение для счётчика. Задаётся с помощью var, как обычная переменная.
i < 10; — проверочная часть. Если условие возвращает true, цикл делает ещё одну итерацию иначе прекращает свою работу.
i++ — дополняющая часть, запускается на каждой итерации после выполнения кода из тела цикла. Меняет значение счётчика.
Накопление значений в цикле
var sum = 0;
for (var i = 1; i <= 5; i++) {
sum += 2;
console.log(sum); // 2 4 6 8 10
}
Проверки в теле цикла
var sum = 0;
for (var i = 1; i <= 5; i++) {
if (i > 2) {
sum += 1;
}
}
Поиск чётного числа
Оператор % или «остаток от деления» возвращает остаток от деления.
10 % 5; // 0 12 % 5; // 2 7 % 3; // 1 5.5 % 2; // 1.5
Если остаток от деления числа на 2 равен 0 — число чётное, иначе нечётное.
Цикл while
Синтаксис:
while (условие) {
действия
}
Действия будут выполняться снова и снова, пока условие не вернёт false.
Накопление значений в цикле
var sum = 0;
var i = 0;
while (i <= 5) {
sum += 1;
i++;
console.log(i); // 1 2 3 4 5
}
Поиск процента от числа
Самый простой способ найти процент от числа — разделить число на 100 и умножить на процент.
// Найдём 2 процента от 1000 1000 / 100 * 2 = 20; // Найдём 7 процентов от 1200 1200 / 100 * 7 = 84;
Массивы
Массив — тип данных (объект), который представляет собой список элементов, у каждого из которых есть свой порядковый номер.
В массиве можно хранить любые данные: строки, булевы значения, числа и даже другие массивы.
Нумерация элементов массива начинается с нуля, поэтому порядковый номер (индекс) первого элемента равен нулю.
В качестве индекса можно использовать переменную.
Используйте команду length, чтобы узнать длину массива (сколько в нём элементов). С её помощью можно получить последний элемент массива.
var numbers = [1, 2, 3, 4, 5]; var index = 3; console.log(numbers[0]); // 1 console.log(numbers[index]); // 4 console.log(numbers.length); // 5 console.log(numbers[numbers.length - 1]); // 5
Массивы можно перебирать в циклах. Например, цикл ниже выводит элементы массива в консоль по очереди и прекращает свою работу, когда i станет равно длине массива.
var numbers = [1, 2, 3, 4, 5];
for (var i = 0; i < numbers.length; i++) {
console.log(numbers[i]); // 1 2 3 4 5
}
Альтернативный способ:
var numbers = [1, 2, 3, 4, 5];
numbers.forEach(function(i) {
console.log(i); // 1 2 3 4 5
});
Запись в массив происходит так же, как чтение, то есть через квадратные скобки.
var numbers = []; var index = 1; numbers[0] = 1; numbers[index] = 2; console.log(numbers); // [1, 2]
Сортировка массива
var numbers = [12, 3, 7, 9, 10, 5];
for (var i = 0; i <= numbers.length - 2; i++) {
var minValue = numbers[i];
for (var j = i + 1; j <= numbers.length - 1; j++) {
if (numbers[j] < minValue) {
minValue = numbers[j];
var swap = numbers[i];
numbers[i] = minValue;
numbers[j] = swap;
}
}
}
console.log(numbers); // [3, 5, 7, 9, 10, 12];
Массив с числами numbers сортируется по возрастанию элементов. На каждой итерации мы сравниваем minValue с остальными элементами массива. Если какой-то из них окажется меньше, чем minValue, он запишется в minValue, перезаписав старое значение, и переместится в начало массива. Переменная swap — вспомогательная переменная, с помощью которой мы можем поменять элементы местами.
Самый короткий способ сортировки:
var numbers = [12, 3, 7, 9, 10, 5];
numbers.sort(function(a, b) {
return a > b;
});
console.log(numbers); // [3, 5, 7, 9, 10, 12];
Суммирование всех значений в массиве
var nums = [100, 20, 3, 7, 9];
var total = nums.reduce(function(a, b) {
return a + b;
});
console.log(total); // 139
Нахождение минимального значения в массиве
var nums = [100, 20, 3, 7, 9];
var index = 0;
var minValue = nums[index];
for (var i = index + 1; i <= nums.length - 1; i++) {
if (nums[i] < minValue) {
minValue = nums[i];
}
}
console.log(minValue); // 3
Альтернативный способ (нахождение минимального и максимального значения в массиве):
var nums = [100, 20, 3, 7, 9];
var min = Math.min.apply(null, nums);
var max = Math.max.apply(null, nums);
console.log("Минимальное значение: " + min); // Минимальное значение: 3
console.log("Максимальное значение: " + max); // Максимальное значение: 100
Функции
Пример функции:
var calculateSum = function (numberFirst, numberSecond) {
var sum = numberFirst + numberSecond;
return sum;
};
calculateSum(); // NaN
calculateSum(2); // NaN
calculateSum(2, 5); // 7
calculateSum(9, 5); // 14
В этом примере:
calculateSum— имя, по которому можно обратиться к функции.numberFirst,numberSecond— параметры функции.return sum;— место кода, где происходит возвращениеsumи выход из функции.calculateSum(2, 5);— аргументы, которые передаются в функции при вызове. Порядок аргументов такой же, как у параметров функции. Первый аргумент2записывается в первый параметрnumberFirst, аргумент5записывается в параметрnumberSecond. Важно соблюдать порядок параметров при вызове функции, чтобы избежать неочевидных ошибок.
Объекты
Объект — тип данных, который хранит в себе информацию в виде пар «ключ-значение». Каждый элемент сопоставлен со своим ключом и порядок элементов совсем неважен.
Синтаксис:
var user = {
name: 'Вася',
age: 25
};
console.log(user.name); // 'Вася'
console.log(user.age); // 25
console.log(user.color); // undefined, такого ключа в объекте нет
user.age++; //Увеличили возраст пользователя на 1
console.log(user.age) // 26
user.name = 'Петя'; //Заменили снаружи значение свойства name
console.log(user.name); // 'Петя'
Передача по ссылке
Объект всегда один, в памяти не создаётся новое место под копию объекта. Каждая переменная содержит не новую отдельную сущность, а ссылку на один-единственный объект. Поэтому когда мы меняем что-то в объекте через одну из переменных, в которой содержится ссылка на него, изменения видны во всех других переменных, будь их хоть двадцать или сорок. Это важная особенность объектов, которую надо запомнить. Она так и называется — передача объектов по ссылке.
var firstUser = {
name: 'Вася',
age: 25
};
var secondUser = firstUser;
console.log(secondUser);
// {"name":"Вася","age":25}
firstUser.name = 'Петя';
console.log(secondUser);
// {"name":"Петя","age":25}
В объектах могут храниться любые типы данных, в том числе и функции. Такие свойства-функции называются методами объектов. Вызов метода записывается так: объект.метод().
Изнутри методов можно обращаться к свойствам и другим методам объекта с помощью ключевого слова this. Оно указывает на текущий объект и называется контекстом вызова.
Важная деталь: пока функция не вызвана, this не содержит никакого значения, контекст появляется только в момент вызова функции.
var user = {
name: 'Вася',
age: 25,
getGreeting: function() {
return 'Привет! Меня зовут ' + this.name;
}
};
console.log(user.getGreeting()); // 'Привет! Меня зовут Вася'
Мапы или словари очень удобны в использовании. В нашем примере они хранят соотношение имени пользователя и лакомства, которое по вкусу именно ему.
var userFavoriteFood = {
Вася: 'рыба'
};
var printFavoriteFood = function(name) {
//Используем скобочную нотацию
return 'Моя любимая еда — ' + userFavoriteFood[name];
};
console.log(printFavoriteFood('Вася')); // 'Моя любимая еда — рыба'
Работа с DOM
Поиск элементов на странице
// Поиск элемента по тегу
var list = document.querySelector('ul');
// Поиск последнего элемента из списка
var lastProduct = document.querySelector('li:last-child');
// Поиск элемента по классу
var price = document.querySelector('.price');
// Поиск третьего элемента из списка товаров
var thirdProduct = document.querySelector('.product:nth-child(3)');
// Поиск всех элементов, подходящих по селектору
var listItems = document.querySelectorAll('.product');
querySelectorAll возвращает список (коллекцию) элементов. Этот список похож на массив, но им не является. Он называется псевдомассив и его можно перебирать с помощью цикла for.
Добавление класса элементу страницы
// Когда ищем элемент по классу, используем точку
var product = document.querySelector('.product');
// Но когда добавляем класс, точки нет!
product.classList.add('product--sale');
Результат работы classList.add() такой же, как при ручном добавлении класса в разметку:
<!-- Исходное состояние разметки --> <li class="product"> … </li> <!-- Состояние после вызова classList.add --> <li class="product product--sale"> … </li>
Свойство DOM-элемент.children возвращает коллекцию дочерних, то есть вложенных, DOM-элементов.
Создание элемента и добавление его в DOM-дерево
var list = document.querySelector('.cards');
// Создаём новый элемент
var card = document.createElement('li');
card.classList.add('card');
// После вызова этого метода новый элемент отрисуется на странице
list.appendChild(card);
Вот что произойдёт с разметкой после вызова appendChild:
<!-- Исходное состояние разметки --> <ul class="cards"> <li class="card">Существующий элемент</li> </ul> <!-- Состояние после вызова appendChild --> <ul class="cards"> <li class="card">Существующий элемент</li> <li class="card">Добавленный элемент</li> </ul>
Работа с текстовым содержимым элемента
<p>Я — <em>текстовый элемент</em>.</p>
var p = document.querySelector('p');
console.log(p.textContent); // 'Я — текстовый элемент.'
p.textContent = 'Теперь у меня новое содержимое.';
console.log(p.textContent); // 'Теперь у меня новое содержимое.'
В HTML содержание тега изменится:
<p>Теперь у меня новое содержимое.</p>