Конспект по learn.javascript.ru
Все значения в JavaScript, за исключением null и undefined, содержат набор вспомогательных функций и значений, доступных «через точку».
Такие функции называют «методами», а значения – «свойствами». Здесь мы рассмотрим основы использования свойств и методов.
Пример объявления функции:
function showMessage() {
alert( 'Привет всем присутствующим!' );
}
Локальные переменные
Функция может содержать локальные переменные, объявленные через var. Такие переменные видны только внутри функции:
function showMessage() {
var message = 'Привет, я - Вася!'; // локальная переменная
alert( message );
}
showMessage(); // 'Привет, я - Вася!'
alert( message ); // <-- будет ошибка, т.к. переменная видна только внутри
Внешние переменные
Функция может обратиться ко внешней переменной, например:
var userName = 'Вася';
function showMessage() {
var message = 'Привет, я ' + userName;
alert(message);
}
showMessage(); // Привет, я Вася
Доступ возможен не только на чтение, но и на запись. При этом, так как переменная внешняя, то изменения будут видны и снаружи функции
var userName = 'Вася';
function showMessage() {
userName = 'Петя'; // (1) присвоение во внешнюю переменную
var message = 'Привет, я ' + userName;
alert( message );
}
showMessage();
alert( userName ); // Петя, значение внешней переменной изменено функцией
Конечно, если бы внутри функции, в строке (1), была бы объявлена своя локальная переменная var userName, то все обращения использовали бы её, и внешняя переменная осталась бы неизменной.
Переменные, объявленные на уровне всего скрипта, называют «глобальными переменными».
В примере выше переменная userName — глобальная.
Делайте глобальными только те переменные, которые действительно имеют общее значение для вашего проекта, а нужные для решения конкретной задачи — пусть будут локальными в соответствующей функции.
Параметры
При вызове функции ей можно передать данные, которые та использует по своему усмотрению.
Например, этот код выводит два сообщения:
function showMessage(from, text) { // параметры from, text
from = "** " + from + " **"; // здесь может быть сложный код оформления
alert(from + ': ' + text);
}
showMessage('Маша', 'Привет!');
showMessage('Маша', 'Как дела?');
Параметры копируются в локальные переменные функции.
Например, в коде ниже есть внешняя переменная from, значение которой при запуске функции копируется в параметр функции с тем же именем. Далее функция работает уже с параметром:
function showMessage(from, text) {
from = '**' + from + '**'; // меняем локальную переменную from
alert( from + ': ' + text );
}
var from = "Маша";
showMessage(from, "Привет");
alert( from ); // старое значение from без изменений, в функции была изменена копия
Аргументы по умолчанию
Функцию можно вызвать с любым количеством аргументов.
Если параметр не передан при вызове — он считается равным undefined.
Например, функцию показа сообщения showMessage(from, text) можно вызвать с одним аргументом:
showMessage("Маша");
При этом можно проверить, и если параметр не передан — присвоить ему значение «по умолчанию»:
function showMessage(from, text) {
if (text === undefined) {
text = 'текст не передан';
}
alert( from + ": " + text );
}
showMessage("Маша", "Привет!"); // Маша: Привет!
showMessage("Маша"); // Маша: текст не передан
При объявлении функции необязательные аргументы, как правило, располагают в конце списка.
Для указания значения «по умолчанию», то есть, такого, которое используется, если аргумент не указан, используется два способа:
Можно проверить, равен ли аргумент undefined, и если да — то записать в него значение по умолчанию. Этот способ продемонстрирован в примере выше.
Использовать оператор ||:
function showMessage(from, text) {
text = text || 'текст не передан';
...
}
Второй способ считает, что аргумент отсутствует, если передана пустая строка, 0, или вообще любое значение, которое в логическом контексте является false.
Возврат значения
Функция может возвратить результат, который будет передан в вызвавший её код.
Например, создадим функцию calcD, которая будет возвращать дискриминант квадратного уравнения по формуле b2 - 4ac:
function calcD(a, b, c) {
return b*b - 4*a*c;
}
var test = calcD(-4, 2, 1);
alert(test); // 20
Для возврата значения используется директива return.
Она может находиться в любом месте функции. Как только до неё доходит управление — функция завершается и значение передается обратно.
Вызовов return может быть и несколько, например:
function checkAge(age) {
if (age > 18) {
return true;
} else {
return confirm('Родители разрешили?');
}
}
var age = prompt('Ваш возраст?');
if (checkAge(age)) {
alert( 'Доступ разрешен' );
} else {
alert( 'В доступе отказано' );
}
Директива return может также использоваться без значения, чтобы прекратить выполнение и выйти из функции.
Например:
function showMovie(age) {
if (!checkAge(age)) {
return;
}
alert( "Фильм не для всех" ); // (*)
// ...
}
В коде выше, если сработал if, то строка (*) и весь код под ней никогда не выполнится, так как return завершает выполнение функции.
Значение функции без return и с пустым return
В случае, когда функция не вернула значение или return был без аргументов, считается что она вернула undefined:
function doNothing() { /* пусто */ }
alert( doNothing() ); // undefined
Обратите внимание, никакой ошибки нет. Просто возвращается undefined.
Ещё пример, на этот раз с return без аргумента:
function doNothing() {
return;
}
alert( doNothing() === undefined ); // true
Выбор имени функции
Имя функции следует тем же правилам, что и имя переменной. Основное отличие — оно должно быть глаголом, т.к. функция — это действие.
Как правило, используются глагольные префиксы, обозначающие общий характер действия, после которых следует уточнение.
Функции, которые начинаются с "show" — что-то показывают:
showMessage(..) // префикс show, "показать" сообщение
Функции, начинающиеся с "get" — получают, и т.п.:
getAge(..) // get, "получает" возраст
calcD(..) // calc, "вычисляет" дискриминант
createForm(..) // create, "создает" форму
checkPermission(..) // check, "проверяет" разрешение, возвращает true/false
Это очень удобно, поскольку взглянув на функцию — мы уже примерно представляем, что она делает, даже если функцию написал совсем другой человек, а в отдельных случаях — и какого вида значение она возвращает.
Одна функция — одно действие
Функция должна делать только то, что явно подразумевается её названием. И это должно быть одно действие.
Если оно сложное и подразумевает поддействия — может быть имеет смысл выделить их в отдельные функции? Зачастую это имеет смысл, чтобы лучше структурировать код.
…Но самое главное — в функции не должно быть ничего, кроме самого действия и поддействий, неразрывно связанных с ним.
Например, функция проверки данных (скажем, "validate") не должна показывать сообщение об ошибке. Её действие — проверить.
Сверхкороткие имена функций
Имена функций, которые используются очень часто, иногда делают сверхкороткими.
Например, во фреймворке jQuery есть функция $, во фреймворке Prototype — функция $$, а в библиотеке LoDash очень активно используется функция с названием из одного символа подчеркивания _.
Конструкция switch заменяет собой сразу несколько if.
Она представляет собой более наглядный способ сравнить выражение сразу с несколькими вариантами.
switch(x) {
case 'value1': // if (x === 'value1')
...
[break]
case 'value2': // if (x === 'value2')
...
[break]
default:
...
[break]
}
var a = 2 + 2;
switch (a) {
case 3:
alert( 'Маловато' );
break;
case 4:
alert( 'В точку!' );
break;
case 5:
alert( 'Перебор' );
break;
default:
alert( 'Я таких значений не знаю' );
}
Если break нет, то выполнение пойдёт ниже по следующим case, при этом остальные проверки игнорируются.
Пример без break:
var a = 2 + 2;
switch (a) {
case 3:
alert( 'Маловато' );
case 4:
alert( 'В точку!' );
case 5:
alert( 'Перебор' );
default:
alert( 'Я таких значений не знаю' );
}
В примере выше последовательно выполнятся три alert:
alert( 'В точку!' );
alert( 'Перебор' );
alert( 'Я таких значений не знаю' );
Группировка case
Несколько значений case можно группировать.
В примере ниже case 3 и case 5 выполняют один и тот же код:
var a = 2+2;
switch (a) {
case 4:
alert('Верно!');
break;
case 3: // (*)
case 5: // (**)
alert('Неверно!');
alert('Немного ошиблись, бывает.');
break;
default:
alert('Странный результат, очень странный');
}
При case 3 выполнение идёт со строки (*), при case 5 — со строки (**).
Оператор switch предполагает строгое равенство ===
Цикл while
Цикл while имеет вид:
while (условие) {
// код, тело цикла
}
Пока условие верно — выполняется код из тела цикла.
Например, цикл ниже выводит i пока i < 3:
var i = 0;
while (i < 3) {
alert( i );
i++;
}
Повторение цикла по-научному называется «итерация». Цикл в примере выше совершает три итерации.
Если бы i++ в коде выше не было, то цикл выполнялся бы (в теории) вечно. На практике, браузер выведет сообщение о «зависшем» скрипте и посетитель его остановит.
Бесконечный цикл можно сделать и проще:
while (true) {
// ...
}
Условие в скобках интерпретируется как логическое значение, поэтому вместо while (i!=0) обычно пишут while (i):
var i = 3;
while (i) { // при i, равном 0, значение в скобках будет false и цикл остановится
alert( i );
i--;
}
Цикл do..while
Проверку условия можно поставить под телом цикла, используя специальный синтаксис do..while:
do {
// тело цикла
} while (условие);
Цикл, описанный, таким образом, сначала выполняет тело, а затем проверяет условие.
Например:
var i = 0;
do {
alert( i );
i++;
} while (i < 3);
Синтаксис do..while редко используется, т.к. обычный while нагляднее — в нём не приходится искать глазами условие и ломать голову, почему оно проверяется именно в конце.
Цикл for
Чаще всего применяется цикл for. Выглядит он так:
for (начало; условие; шаг) {
// ... тело цикла ...
}
Пример цикла, который выполняет alert(i) для i от 0 до 2 включительно (до 3):
var i;
for (i = 0; i < 3; i++) {
alert( i );
}
Здесь:
Начало: i=0.
Условие: i<3.
Шаг: i++.
Тело: alert(i), т.е. код внутри фигурных скобок (они не обязательны, если только одна операция)
Цикл выполняется так:
Начало: i=0 выполняется один-единственный раз, при заходе в цикл.
Условие: i<3 проверяется перед каждой итерацией и при входе в цикл, если оно нарушено, то происходит выход.
Тело: alert(i).
Шаг: i++ выполняется после тела на каждой итерации, но перед проверкой условия.
Идти на шаг 2.
Иными словами, поток выполнения: начало → (если условие → тело → шаг) → (если условие → тело → шаг) → … и так далее, пока верно условие.
Please note:
В цикле также можно определить переменную:
for (var i = 0; i < 3; i++) {
alert(i); // 0, 1, 2
}
Эта переменная будет видна и за границами цикла, в частности, после окончания цикла i станет равно 3.
Пропуск частей for
Любая часть for может быть пропущена.
Например, можно убрать начало. Цикл в примере ниже полностью идентичен приведённому выше:
var i = 0;
for (; i < 3; i++) {
alert( i ); // 0, 1, 2
}
Можно убрать и шаг:
var i = 0;
for (; i < 3;) {
alert( i );
// цикл превратился в аналог while (i<3)
}
А можно и вообще убрать всё, получив бесконечный цикл:
for (;;) {
// будет выполняться вечно
}
При этом сами точки с запятой ; обязательно должны присутствовать, иначе будет ошибка синтаксиса.
for..in
Существует также специальная конструкция for..in для перебора свойств объекта.
Мы познакомимся с ней позже, когда будем говорить об объектах.
Прерывание цикла: break
Выйти из цикла можно не только при проверке условия но и, вообще, в любой момент. Эту возможность обеспечивает директива break.
Например, следующий код подсчитывает сумму вводимых чисел до тех пор, пока посетитель их вводит, а затем — выдаёт:
var sum = 0;
while (true) {
var value = +prompt("Введите число", '');
if (!value) break; // (*)
sum += value;
}
alert( 'Сумма: ' + sum );
Директива break в строке (*), если посетитель ничего не ввёл, полностью прекращает выполнение цикла и передаёт управление на строку за его телом, то есть на alert.
Вообще, сочетание «бесконечный цикл + break» — отличная штука для тех ситуаций, когда условие, по которому нужно прерваться, находится не в начале-конце цикла, а посередине.
Следующая итерация: continue
Директива continue прекращает выполнение текущей итерации цикла.
Она — в некотором роде «младшая сестра» директивы break: прерывает не весь цикл, а только текущее выполнение его тела, как будто оно закончилось.
Её используют, если понятно, что на текущем повторе цикла делать больше нечего.
Например, цикл ниже использует continue, чтобы не выводить чётные значения:
for (var i = 0; i < 10; i++) {
if (i % 2 == 0) continue;
alert(i);
}
Для чётных i срабатывает continue, выполнение тела прекращается и управление передаётся на следующий проход for.
Директива continue позволяет обойтись без скобок
Цикл, который обрабатывает только нечётные значения, мог бы выглядеть так:
for (var i = 0; i < 10; i++) {
if (i % 2) {
alert( i );
}
}
С технической точки зрения он полностью идентичен. Действительно, вместо continue можно просто завернуть действия в блок if. Однако, мы получили дополнительный уровень вложенности фигурных скобок. Если код внутри if более длинный, то это ухудшает читаемость, в отличие от варианта с continue.
Нельзя использовать break/continue справа от оператора '?'
Обычно мы можем заменить if на оператор вопросительный знак '?'.
То есть, запись:
if (условие) {
a();
} else {
b();
}
…Аналогична записи:
условие ? a() : b();
В обоих случаях в зависимости от условия выполняется либо a() либо b().
Но разница состоит в том, что оператор вопросительный знак '?', использованный во второй записи, возвращает значение.
Синтаксические конструкции, которые не возвращают значений, нельзя использовать в операторе '?'.
К таким относятся большинство конструкций и, в частности, break/continue.
Поэтому такой код приведёт к ошибке:
(i > 5) ? alert(i) : continue;
Впрочем, как уже говорилось ранее, оператор вопросительный знак '?' не стоит использовать таким образом. Это — всего лишь ещё одна причина, почему для проверки условия предпочтителен if.
Метки для break/continue
Бывает нужно выйти одновременно из нескольких уровней цикла.
Например, внутри цикла по i находится цикл по j, и при выполнении некоторого условия мы бы хотели выйти из обоих циклов сразу:
outer: for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
var input = prompt('Значение в координатах '+i+','+j, '');
// если отмена ввода или пустая строка -
// завершить оба цикла
if (!input) break outer; // (*)
}
}
alert('Готово!');
В коде выше для этого использована метка.
Метка имеет вид "имя:", имя должно быть уникальным. Она ставится перед циклом, вот так:
outer: for (var i = 0; i < 3; i++) { ... }
Можно также выносить её на отдельную строку:
outer:
for (var i = 0; i < 3; i++) { ... }
Вызов break outer ищет ближайший внешний цикл с такой меткой и переходит в его конец.
В примере выше это означает, что будет разорван самый внешний цикл и управление перейдёт на alert.
Директива continue также может быть использована с меткой, в этом случае управление перепрыгнет на следующую итерацию цикла с меткой.
Итого
JavaScript поддерживает три вида циклов:
while — проверка условия перед каждым выполнением.
do..while — проверка условия после каждого выполнения.
for — проверка условия перед каждым выполнением, а также дополнительные настройки.
Чтобы организовать бесконечный цикл, используют конструкцию while(true). При этом он, как и любой другой цикл, может быть прерван директивой break.
Если на данной итерации цикла делать больше ничего не надо, но полностью прекращать цикл не следует — используют директиву continue.
Обе этих директивы поддерживают «метки», которые ставятся перед циклом. Метки — единственный способ для break/continue повлиять на выполнение внешнего цикла.
Заметим, что метки не позволяют прыгнуть в произвольное место кода, в JavaScript нет такой возможности.
Для операций над логическими значениями в JavaScript есть || (ИЛИ), && (И) и ! (НЕ).
var year = prompt('В каком году появилась спецификация ECMA-262 5.1?', '');
if (year < 2011) {
alert( 'Это слишком рано..' );
} else if (year > 2011) {
alert( 'Это поздновато..' );
} else {
alert( 'Да, точно в этом году!' );
}
Оператор вопросительный знак '?'
Иногда нужно в зависимости от условия присвоить переменную. Например:
var access;
var age = prompt('Сколько вам лет?', '');
if (age > 14) {
access = true;
} else {
access = false;
}
alert(access);
Оператор вопросительный знак '?' позволяет делать это короче и проще.
Он состоит из трех частей:
условие ? значение1 : значение2
Проверяется условие, затем если оно верно — возвращается значение1, если неверно — значение2, например:
access = (age > 14) ? true : false;
Оператор '?' выполняется позже большинства других, в частности — позже сравнений, поэтому скобки можно не ставить:
access = age > 14 ? true : false;
«Тернарный оператор»
Вопросительный знак — единственный оператор, у которого есть аж три аргумента, в то время как у обычных операторов их один-два. Поэтому его называют «тернарный оператор».
var age = prompt('возраст?', 18);
var message = (age < 3) ? 'Здравствуй, малыш!' :
(age < 18) ? 'Привет!' :
(age < 100) ? 'Здравствуйте!' :
'Какой необычный возраст!';
alert( message );
Иногда оператор вопросительный знак '?' используют как замену if:
var company = prompt('Какая компания создала JavaScript?', '');
(company == 'Netscape') ?
alert('Да, верно') : alert('Неправильно');
Работает это так: в зависимости от условия, будет выполнена либо первая, либо вторая часть после '?'.
Результат выполнения не присваивается в переменную, так что пропадёт (впрочем, alert ничего не возвращает).
alert выводит сообщение.
prompt выводит сообщение и ждёт, пока пользователь введёт текст, а затем возвращает введённое значение или null, если ввод отменён (CANCEL/Esc).
confirm выводит сообщение и ждёт, пока пользователь нажмёт «OK» или «CANCEL» и возвращает true/false.
Для проверки равенства без преобразования типов используются операторы строгого равенства === (тройное равно) и !==.
В JavaScript есть логические значения true (истина) и false (ложь). Операторы сравнения возвращают их.
Строки сравниваются побуквенно.
Значения разных типов приводятся к числу при сравнении, за исключением строгого равенства === (!==).
Значения null и undefined равны == друг другу и не равны ничему другому. В других сравнениях (с участием >,<) их лучше не использовать, так как они ведут себя не как 0.
В JavaScript есть логические значения true (истина) и false (ложь). Операторы сравнения возвращают их.
Строки сравниваются побуквенно.
Значения разных типов приводятся к числу при сравнении, за исключением строгого равенства === (!==).
Значения null и undefined равны == друг другу и не равны ничему другому. В других сравнениях (с участием >,<) их лучше не использовать, так как они ведут себя не как 0.
У операторов есть своя терминология, которая используется во всех языках программирования.
Операнд — то, к чему применяется оператор. Например: 5 * 2 — оператор умножения с левым и правым операндами. Другое название: «аргумент оператора».
Унарным называется оператор, который применяется к одному выражению. Например, оператор унарный минус "-" меняет знак числа на противоположный:
var x = 1;
x = -x;
alert( x ); // -1, применили унарный минус
Бинарным называется оператор, который применяется к двум операндам. Тот же минус существует и в бинарной форме:
var x = 1, y = 3;
alert( y - x ); // 2, бинарный минус
Таблица приоритетов https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
Взятие остатка %
Оператор взятия остатка % интересен тем, что, несмотря на обозначение, никакого отношения к процентам не имеет.
Его результат a % b — это остаток от деления a на b.
Например:
alert( 5 % 2 ); // 1, остаток от деления 5 на 2
alert( 8 % 3 ); // 2, остаток от деления 8 на 3
alert( 6 % 3 ); // 0, остаток от деления 6 на 3
Инкремент/декремент: ++, --
Одной из наиболее частых операций в JavaScript, как и во многих других языках программирования, является увеличение или уменьшение переменной на единицу.
Для этого существуют даже специальные операторы:
Инкремент ++ увеличивает на 1:
var i = 2;
i++; // более короткая запись для i = i + 1.
alert(i); // 3
Декремент -- уменьшает на 1:
var i = 2;
i--; // более короткая запись для i = i - 1.
alert(i); // 1
Вызывать эти операторы можно не только после, но и перед переменной: i++ (называется «постфиксная форма») или ++i («префиксная форма»).
Обе эти формы записи делают одно и то же: увеличивают на 1.
Тем не менее, между ними существует разница. Она видна только в том случае, когда мы хотим не только увеличить/уменьшить переменную, но и использовать результат в том же выражении.
Например:
var i = 1;
var a = ++i; // (*)
alert(a); // 2
В строке (*) вызов ++i увеличит переменную, а затем вернёт ее значение в a. Так что в a попадёт значение i после увеличения.
Постфиксная форма i++ отличается от префиксной ++i тем, что возвращает старое значение, бывшее до увеличения.
В примере ниже в a попадёт старое значение i, равное 1:
var i = 1;
var a = i++; // (*)
Если результат оператора не используется, а нужно только увеличить/уменьшить переменную — без разницы, какую форму использовать:
var i = 0;
i++;
++i;
alert( i ); // 2
Если хочется тут же использовать результат, то нужна префиксная форма:
var i = 0;
alert( ++i ); // 1
Если нужно увеличить, но нужно значение переменной до увеличения — постфиксная форма:
var i = 0;
alert( i++ ); // 0
Поддерживаются следующие побитовые операторы:
AND(и) ( & )
OR(или) ( | )
XOR(побитовое исключающее или) ( ^ )
NOT(не) ( ~ )
LEFT SHIFT(левый сдвиг) ( << )
RIGHT SHIFT(правый сдвиг) ( >> )
ZERO-FILL RIGHT SHIFT(правый сдвиг с заполнением нулями) ( >>> )
Они используются редко, поэтому вынесены в отдельную главу Побитовые операторы.\
Сокращённая арифметика с присваиванием
Часто нужно применить оператор к переменной и сохранить результат в ней же, например:
var n = 2;
n = n + 5;
n = n * 2;
Эту запись можно укоротить при помощи совмещённых операторов, вот так:
var n = 2;
n += 5; // теперь n=7 (работает как n = n + 5)
n *= 2; // теперь n=14 (работает как n = n * 2)
alert( n ); // 14
Оператор typeof
Оператор typeof возвращает тип аргумента.
У него есть два синтаксиса: со скобками и без:
Синтаксис оператора: typeof x.
Синтаксис функции: typeof(x).
Работают они одинаково, но первый синтаксис короче.
Результатом typeof является строка, содержащая тип:
typeof undefined // "undefined"
typeof 0 // "number"
typeof true // "boolean"
typeof "foo" // "string"
typeof {} // "object"
typeof null // "object" (1)
typeof function(){} // "function" (2)
Последние две строки помечены, потому что typeof ведет себя в них по-особому.
Результат typeof null == "object" — это официально признанная ошибка в языке, которая сохраняется для совместимости. На самом деле null — это не объект, а отдельный тип данных.
Функции мы пройдём чуть позже. Пока лишь заметим, что функции не являются отдельным базовым типом в JavaScript, а подвидом объектов. Но typeof выделяет функции отдельно, возвращая для них "function". На практике это весьма удобно, так как позволяет легко определить функцию.
Переменные из нескольких слов пишутся вместеВотТак.
Например:
var borderLeftWidth;
Этот способ записи называется «верблюжьей нотацией» или, по-английски, «camelCase».
Существует альтернативный стандарт, когда несколько слов пишутся через знак подчеркивания '_':
var border_left_width;
Преимущественно в JavaScript используется вариант borderLeftWidth, в частности во встроенных языковых и браузерных функциях. Поэтому целесообразно остановиться на нём.
Ещё одна причина выбрать «верблюжью нотацию» — запись в ней немного короче, чем c подчеркиванием, т.к. не нужно вставлять '_'.
Имя переменной должно максимально чётко соответствовать хранимым в ней данным.
Можно даже объявить несколько переменных сразу:
var user = 'John', age = 25, message = 'Hello';
Можно объявить две переменные и копировать данные из одной в другую:
var hello = 'Hello world!';
var message;
// скопировали значение
message = hello;
alert( hello ); // Hello world!
alert( message ); // Hello world!
Имя переменной может состоять из: букв, цифр, символов $ и _
Первый символ не должен быть цифрой.
Регистр букв имеет значение
Переменные apple и AppLE — две разные переменные.
Константы
Константа — это переменная, которая никогда не меняется. Как правило, их называют большими буквами, через подчёркивание. Например:
var COLOR_RED = "#F00";
var COLOR_GREEN = "#0F0";
var COLOR_BLUE = "#00F";
var COLOR_ORANGE = "#FF7F00";
var color = COLOR_ORANGE;
alert( color ); // #FF7F00
Технически, константа является обычной переменной, то есть её можно изменить. Но мы договариваемся этого не делать.
Зачем нужны константы? Почему бы просто не писать var color = "#FF7F00"?
Во-первых, константа COLOR_ORANGE — это понятное имя. По присвоению var color="#FF7F00" непонятно, что цвет — оранжевый. Иными словами, константа COLOR_ORANGE является «понятным псевдонимом» для значения #FF7F00.
Во-вторых, опечатка в строке, особенно такой сложной как #FF7F00, может быть не замечена, а в имени константы её допустить куда сложнее.
Константы используют вместо строк и цифр, чтобы сделать программу понятнее и избежать ошибок.
"use strict";
// этот код будет работать по современному стандарту ES5
/*
ES5-shim
Браузер IE8 поддерживает только совсем старую версию стандарта JavaScript, а именно ES3.
К счастью, многие возможности современного стандарта можно добавить в этот браузер, подключив библиотеку ES5 shim, а именно — скрипты es5-shim.js и es5-sham.js из
*/
Простые элементы script исполняются синхронно. Как правило, оно вполне нормально, но есть один нюанс.
Пока браузер не загрузит и не выполнит внешний скрипт, он не покажет часть страницы под ним.
В ряде случаев это совсем неуместно. Например, мы подключаем внешний скрипт, который показывает рекламу или вставляет счётчик посещений, а затем идёт наша страница. Конечно, неправильно, что пока счётчик или реклама не подгрузятся — оставшаяся часть страницы не показывается. Счётчик посещений не должен никак задерживать отображение страницы сайта. Реклама — это дополнение к странице, она не должна как-то тормозить сайт и нарушать его функционал.
А что, если сервер, с которого загружается внешний скрипт, перегружен? Посетитель в этом случае может ждать очень долго.
<script src="//other-domain.com/1.js"></script>
<script src="2.js"></script>
Спецификация: Скачивать вместе, выполнять по порядку после загрузки CSS, блокировать рендеринг до завершения.
Браузеры: Да, сэр!
Defer
<script src="//other-domain.com/1.js" defer></script>
<script src="2.js" defer></script>
Спецификация: Скачивать вместе, выполнять по порядку непосредственно перед событием DOMContentLoaded. Игнорировать defer для скриптов, у которых нет src.
IE < 10: Ну, может быть, я выполню 2.js где-то посередине исполнения 1.js. Это же забавно, согласитесь?
Браузеры в красном: Понятия не имею, что это еще за defer такой, буду выполнять скрипты так, как если бы его не было.
Другие браузеры: Окей, но вообще-то, я могу и не игнорировать defer на скриптах, у которых нет src.
Async
<script src="//other-domain.com/1.js" async=""></script>
<script src="2.js" async></script>
Спецификация: Скачивать вместе, выполнять в том порядке, в котором они будут загружены.
Браузеры в красном: Что это за async? Буду загружать скрипты, как если бы его не было.
Остальные браузеры: Оу, ну окей.
Async false
[
'1.js',
'2.js'
].forEach(function(src) {
var script = document.createElement('script');
script.src = src;
script.async = false;
document.head.appendChild(script);
});
Спецификация: Скачивать вместе, выполнять по порядку тогда, когда все загрузятся.
Firefox < 3.6, Opera: Понятия не имею, что это за async, но так уж вышло, что я выполняю скрипты, которые добавляются через JS, в том порядке, в котором они были добавлены.
Safari 5.0: Так, я вроде знаю, что такое async, но не понимаю, как можно устанавливать его значение в false через JS. Знаете что? Я выполню ваши скрипты в таком порядке, в котором они загрузятся, а там уж как пойдет.
IE < 10: Ничего не знаю про async, но меня можно убедить с помощью onreadystatechange.
Остальные браузеры в красном: Понятия не имею, что это за async. Буду исполнять ваши скрипты по мере их поступления, в том порядке, в котором они загрузятся.
Все остальные: Я твой друг, сделаю все по инструкции!
PS: Просто помещайте скрипты в конец body.
//Введение в JavaScript
/*
Что такое JavaScript?
JavaScript изначально создавался для того, чтобы сделать web-странички «живыми».
Программы на этом языке называются скриптами.
В браузере они подключаются напрямую к HTML и, как только загружается
страничка — тут же выполняются.
Программы на JavaScript — обычный текст. Они не требуют какой-то специальной подготовки.
JavaScript может выполняться не только в браузере, а где угодно, нужна лишь специальная
программа — интерпретатор.
Процесс выполнения скрипта называют «интерпретацией».
Компиляция и интерпретация, для программистов
Для выполнения программ, не важно на каком языке,
существуют два способа: «компиляция» и «интерпретация».
Компиляция — это когда исходный код программы, при помощи специального инструмента,
другой программы, которая называется «компилятор», преобразуется в другой язык,
как правило — в машинный код. Этот машинный код затем распространяется и запускается.
При этом исходный код программы остаётся у разработчика.
Интерпретация — это когда исходный код программы получает другой инструмент,
который называют «интерпретатор», и выполняет его «как есть».
При этом распространяется именно сам исходный код (скрипт).
Этот подход применяется в браузерах для JavaScript.
Справочники и спецификации
http://learn.javascript.ru/pre-coding
<script> ... </script>
Тег script содержит исполняемый код.
Предыдущие стандарты HTML требовали обязательного указания атрибута type,
но сейчас он уже не нужен. Достаточно просто <script>.
Браузер, когда видит <script>:
Начинает отображать страницу, показывает часть документа до script
Встретив тег script, переключается в JavaScript-режим и не показывает, а исполняет его содержимое.
Закончив выполнение, возвращается обратно в HTML-режим и только тогда
отображает оставшуюся часть документа.
Если JavaScript-кода много — его выносят в отдельный файл, который подключается в HTML:
<script src="/path/to/script.js"></script>
Если указан атрибут src, то содержимое тега игнорируется.
В одном теге SCRIPT нельзя одновременно подключить внешний скрипт и указать код.
Вот так не cработает:
<script src="file.js">
alert(1); // так как указан src, то внутренняя часть тега игнорируется
</script>
Нужно выбрать: либо SCRIPT идёт с src, либо содержит код. Тег выше следует разбить на два: один — с src, другой — с кодом, вот так:
<script src="file.js"></script>
<script>
alert( 1 );
</script>
Асинхронные скрипты: defer/async
Браузер загружает и отображает HTML постепенно.
Особенно это заметно при медленном интернет-соединении:
браузер не ждёт, пока страница загрузится целиком,
а показывает ту часть, которую успел загрузить.
Если браузер видит тег <script>, то он по стандарту обязан
сначала выполнить его, а потом показать оставшуюся часть страницы.
Такое поведение называют «синхронным». Как правило, оно вполне нормально, но есть важное следствие.
Если скрипт — внешний, то пока браузер не выполнит его, он не покажет часть страницы под ним.
*/