Основы JavaScript
JavaScript был создан в 1995 году как способ добавления программ на веб-страницы в браузере Netscape Navigator. Сегодня этот язык принят всеми другими основными веб-браузерами и стал одним из самых популярных языков программирования в мире.
Настройка среды
В этом уроке у нас будет много примеров фрагментов кода. Чтобы выполнить код, мы можем просто открыть браузер, перейти в Инструменты разработчика -> Консоль:
Или вы можете установить Node.js на свой компьютер, что позволит вам запускать программы JavaScript с помощью командных терминалов.
Типы данных в JavaScript
В компьютерном мире все зависит от данных. Что делает компьютерная программа, так это, по сути, берет некоторые входные данные, обрабатывает их, а затем возвращает некоторые выходные данные. В этом разделе мы поговорим о некоторых типах данных, которые может обрабатывать JacaScript.
Numbers
Числа — это самое простое, потому что они работают точно так же, как то, что вы изучали на уроках математики в начальной школе.
// Integer
100
// Fractional Number
10.56
//Scientific Notation
3.14e5 // 3.14 * 10^5 = 314000
Основное использование чисел - выполнение арифметических операций.
3 + 5 * 2 // -> 13
Так же, как вы учились в начальной школе, умножение и деление происходят первыми. Однако вы можете изменить это, используя круглые скобки.
(3 + 5) * 2 // -> 16
Есть один оператор, который вы можете не узнать, это операция по модулю (%
). X%
Y
вычисляет остаток от деления X
на Y
. Например:
25 % 5 // -> 0
25 % 10 // -> 5
25 % 15 // -> 10
Strings
Strings используются для представления текстов, и все они заключены в кавычки, например:
"This is a string."
'This is also a string.'
И одинарные, и двойные кавычки работают одинаково, если открывающая и закрывающая кавычки совпадают.
Всякий раз, когда внутри строки встречается обратная косая черта (\
), это означает, что символ после него имеет особое значение. Например, если за обратной косой чертой следует буква n (\n
), это будет интерпретировано вашим компьютером как новая строка:
"This is the first line\nThis is the second line"
Выводимый текст будет выглядеть так:
This is the first line
This is the second line
Операцию +
также можно использовать со строками. Но очевидно, что строки нельзя использовать в арифметических операциях, знак плюс здесь означает конкатенацию (соединение двух строк вместе).
"con" + "cat" + "e" + "nate" // -> "concatenate"
Наконец, в JavaScript есть особый тип строк — строки в обратных кавычках, обычно называемые шаблонными литералами. Это позволяет нам вставлять другие значения в строку:
`half of 100 is ${100 / 2}`
В этом примере будет вычислено деление внутри ${}
, результат будет преобразован в строку и напечатан в этой позиции. Итак, этот пример даст нам:
half of 100 is 50
Boolean values
Тип Boolean включает только два значения: true
и false
. Сравнение является наиболее распространенным способом получения логических значений.
console.log(1 == 1) // -> true
console.log(1 > 2) // -> false
console.log(1 < 0) // -> false
console.log(1 != 2) // -> true
В этом примере ==
означает «равно», а !=
означает «не равно». Другие подобные операторы включают >=
(больше или равно) и <=
(меньше или равно).
Есть три логических оператора, которые мы можем применять к логическим значениям в JavaScript: &&
(и), ||
(или), и !
(нет).
Оператор &&
обозначает логическое and
, он возвращает true
только в том случае, если оба переданных ему значения истинны.
console.log(true && false) // -> false
console.log(false && true) // -> false
console.log(false && false) // -> false
console.log(true && true) // -> true
||
оператор обозначает логическое or
, он возвращает истину, если любое из данных ему значений true
.
console.log(true || false) // -> true
console.log(false || true) // -> true
console.log(false || false) // -> false
console.log(true || true) // -> true
!
оператор обозначает логическое «нет» и переворачивает заданное значение.
console.log(!true) // -> false
console.log(!false) // -> true
Мы также можем смешивать арифметические операции со сравнениями и логическими операциями.
1 + 1 == 2 && 1 + 1 < 0
В этом примере 1 + 1 == 2
дает нам true
, а 1 + 1 < 0
дает нам false
, поэтому мы имеем:
true && false // -> false
Пустые значения
В JavaScript есть два специальных значения: null и undefined. Они указывают на отсутствие значимого значения. В компьютерных программах есть много операций, которые не дают значимых результатов (которые мы увидим позже в этом курсе), и эти результаты будут обозначаться нулевыми или неопределенными.
Эти два значения практически не отличаются друг от друга, более того, в большинстве случаев их можно рассматривать как взаимозаменяемые. Тот факт, что есть два разных значения, указывающих на одно и то же, является просто случайностью дизайна JavaScript.
Преобразование типа данных
JavaScript — очень интеллектуальный язык программирования, он всегда будет пытаться выполнить программу, которую вы ему даете, даже если эта программа не имеет смысла. Например:
console.log(8 * null) // -> 0
console.log("5" - 1) // -> 4
console.log("5" + 1) // -> "51"
В первом примере null
преобразуется в число 0
, а во втором примере строка «5
» становится числом 5
. Однако в третьем примере число 1
преобразуется в строку «1
», и знак «плюс» здесь означает конкатенацию, поэтому результатом становится «51
».
Я знаю, что эти результаты повсюду, и они не имеют никакого смысла. Вот почему вы никогда не должны пытаться делать это при кодировании, даже если это «работает», это приведет к неожиданным результатам.
Структуры программ в JavaScript
Заявления и привязки
В компьютерном программировании вы можете думать о «программе» как о инструкции по решению сложной проблемы. Каждая инструкция/предложение в этом руководстве называется утверждением. В JavaScript оператор всегда должен заканчиваться точкой с запятой (;
).
let num = 10;
Этот пример называется привязкой или переменной. Он связывает значение 10
с именем num
с помощью оператора =
, что позволяет нам сделать что-то вроде этого:
let num = 10;
console.log(num * num); // -> 100
Ключевое слово let
указывает, что этот оператор будет определять привязку. Когда формируется привязка, это не значит, что имя привязывается к значению навсегда, мы по-прежнему можем использовать оператор =
на существующих привязках.
let num = 10;
console.log(num); // -> 10
num = 20;
console.log(num); // -> 20
Обратите внимание, что мы использовали ключевое слово let
только в строке 1. Это потому, что let
используется только для объявления привязки, а в строке 5 мы просто обновляем значение, привязанное к переменной num
.
let num1 = 10;
let num2 = 20;
console.log(num1); // -> 10
console.log(num2); // -> 20
num2 = num1;
console.log(num1); // -> 10
console.log(num2); // -> 10
let num = 10;
num = num - 5;
console.log(num); // -> 5
Ключевые слова const
и var
также можно использовать для создания привязок точно так же, как и let
, однако они различаются по областям действия, которые мы подробно рассмотрим позже.
Functions
Функция — это часть программы, которая возвращает значение или имеет некоторые побочные эффекты, или и то, и другое. Например, функция console.log()
, которую мы видели несколько раз, используется для вывода значений в терминал.
Или, в этом примере, функция prompt()
покажет вам диалоговое окно, которое запрашивает ввод данных пользователем, и этот ввод будет связан с переменной num
.
let num = prompt("Enter A Number");
console.log(num);
И отображение диалога, и вывод текста на экран являются побочными эффектами. Функция также может быть полезна без побочного эффекта. Например:
console.log(Math.max(2,4,6,8));
Функция Math.max()
не имеет побочных эффектов, она просто берет набор чисел и возвращает наибольшее из них.
Все эти функции встроены в JavaScript. Однако мы можем создавать собственные функции с помощью JavaScript. Мы обсудим эту тему в следующем разделе.
Оператор if
Оператор if
предлагает нам способ выполнения разных фрагментов кода в разных условиях. Например:
let num = prompt("Enter A Number");
if (num < 10) {
console.log("Small");
} else {
console.log("Large");
}
Эта программа просит вас ввести число, если оно меньше 10, console.log("Small");
будет выполнено, и программа выведет "Small"
. Если число больше 10, программа выведет "Large"
.
Мы также можем связать несколько пар if
/else
, если нам нужно рассмотреть несколько условий:
if (num < 10) {
console.log("Small");
} else if (num < 100) {
console.log("Medium");
} else {
console.log("Large");
}
Эта программа сначала проверит, меньше ли число 10, если да, то выведет "Small"
. Если число больше 10, программа затем проверит, меньше ли оно 100. Если да, программа выведет "Medium"
. Наконец, если число больше 100, программа покажет "Large"
.
Циклы for
Циклы for
предлагают нам способ выполнять один и тот же код снова и снова, пока выполняются некоторые условия.
for (let num = 0; num <= 12; num = num + 2) {
console.log(num);
}
Цикл for
принимает три выражения, разделенные двумя точками с запятой. В этом примере первое выражение let num = 0
объявляет новую переменную num
, начальное значение которой равно 0. Второе выражение означает, что цикл будет повторяться до тех пор, пока не будет нарушено условие num <= 12
(num
больше 12). Последнее выражение означает, что для каждой итерации число будет увеличиваться на 2.
Циклы while
Циклы while
работают аналогичным образом, за исключением того, что они принимают только одно выражение. На самом деле, мы можем легко изменить наш предыдущий пример цикла for
на цикл while
.
let num = 0;
while (num <= 12) {
console.log(num);
num = num + 2;
}
В этом примере мы сначала инициировали переменную num
вне цикла while
. Внутри круглых скобок после ключевого слова while
находится выражение, проверяющее, должен ли цикл продолжаться. Наконец, мы обновляем значение num
в конце цикла while
.
Циклы do while
Цикл do-while
отличается от цикла while
только в одном: он гарантирует выполнение тела цикла хотя бы один раз.
let num = 10;
do {
num = num + 1;
console.log(num);
} while (num <= 1);
На этот раз начальное значение num
равно 10, что нарушает условие продолжения цикла. Но поскольку это цикл do-while
, тело все равно выполняется один раз. Если бы это был цикл while
, он бы вообще не выполнялся.
Вырваться из петли
Нарушение условия продолжения цикла — не единственный способ остановить цикл. Например, вас просят найти число, которое больше 100 и делится на 9 (напомним, что оператор % используется для вычисления напоминания, поэтому, если остаток x/9 равен 0, это означает, что x делится на 9). Мы можем использовать цикл for для решения этой проблемы:
for (let num = 100; ; num = num + 1) {
if (num % 9 == 0) {
console.log(num);
break;
}
}
Обратите внимание, что у нас нет выражения, определяющего, должен ли цикл продолжаться. Вместо этого у нас есть оператор if
с ключевым словом break
внутри, которое вырвется из цикла, если оно будет выполнено. Если вы удалите ключевое слово break
, этот цикл for
станет бесконечным и будет работать вечно, чего вам всегда следует избегать.
Функции в JavaScript
Ранее мы видели некоторые функции, поставляемые с JavaScript. В этом разделе мы сосредоточимся на определении наших собственных пользовательских функций в JavaScript. Функцию можно рассматривать как фрагмент кода, заключенный в значение, что позволяет нам повторно использовать этот фрагмент кода снова и снова. В этой статье мы поговорим о трех разных способах определения функции в JavaScript.
Первый способ — определить функции как значения и привязать это значение к имени.
let square = function(x) {
return x*x;
};
Функция создается с помощью ключевого слова function
, и в качестве входных данных она будет принимать набор параметров, в данном случае только x
. У функции также должно быть тело, в котором вы возвращаете вывод с помощью ключевого слова return
или имеете какой-то побочный эффект. Наконец, функции в качестве значения будет присвоен square
имени, который нам нужно использовать для вызова этой функции.
Кроме того, помните, что точка с запятой (;
) в конце необходима, потому что это все еще полный оператор, в котором вы объявляете привязку, за исключением того, что здесь значение является функцией.
console.log(square(10)); // -> 100
Функция может иметь более одного параметра или вообще не иметь параметров (пустой набор параметров).
const sleep = function() {
console.log("zzzzzzzzzzzzzzzzzzzzzz");
};
var multiply3 = function(x, y, z) {
return x * y * z;
};
Как видите, функция может иметь только побочный эффект и ничего не возвращать.
Второй метод немного короче, он объявляет функцию с помощью ключевого слова function
и не требует точки с запятой в конце:
function square(x) {
return x*x;
}
Метод также позволяет нам сделать что-то вроде этого:
sleep();
multiply3(2,3,4);
function sleep() {
console.log("zzzzzzzzzzzzzzzzzzzzzz");
}
function multiply3(x, y, z) {
return x*y*z;
}
Здесь мы помещаем объявления функций после оператора, который их вызывает, и код все еще работает. Теперь мы можем собрать все функции в одном месте, что очень удобно для дальнейшего обслуживания.
Третий метод называется стрелочными функциями. Вместо ключевого слова function
мы можем использовать стрелку (=>
) для объявления функции.
const square = (x) => {
return x*x;
}
Это точно такая же функция Square()
, которую мы видели раньше, и она работает точно так же. Тогда почему в JavaScript есть и стрелочные функции, и ключевое слово function
? Хотя в некоторых случаях это позволяет нам писать более короткие функции.
Если функция имеет только один параметр, вы можете опустить круглые скобки вокруг списка параметров. А если в теле функции всего один оператор, фигурные скобки и ключевое слово return тоже можно опустить. Тогда наша функция Square()
становится такой:
const square = x => x * x;
Привязки и области видимости
Прежде чем мы углубимся в тему функций, вернемся к первому методу. Вы могли заметить, что мы определили функции в примерах, используя разные ключевые слова, let
, const
и var
. В чем именно их отличия?
Во-первых, нам нужно понять концепцию масштаба. Это часть программы, в которой доступна привязка. Если привязка определена вне каких-либо функций или блоков (блоками могут быть операторы if
, циклы for
или while
и т. д.), вы можете ссылаться на эту привязку, где хотите. Это называется глобальной привязкой.
Если привязка объявлена внутри функции или блока с помощью let
или const
, эта привязка будет доступна только внутри функции/блока, и это называется локальной привязкой. Однако, если привязка определена с использованием ключевого слова var
, то эта привязка также будет доступна извне function/block.
let x = 10;
if (true) {
let y = 20;
var z = 30;
console.log(x + y + z); // -> all three variables are accessible here
}
console.log(x + z); // -> you cannot "see" y from here, but z is still accessible
Теперь, в чем разница между let
и const
? Как следует из названия, const
означает константу, что означает, что если привязка объявлена с помощью const
, вы не можете изменить ее значение (в отличие от let
).
Необязательные аргументы
JavaScript очень универсален, когда дело доходит до количества параметров, которые вы передаете функции. Например, у нас есть функция Square()
, которую мы определили ранее, которая должна принимать один аргумент.
function square(x) { return x * x; }
console.log(square(4, true, "qwerty"));
В этом примере мы передали функции Square()
более одного аргумента, и она просто игнорирует лишние аргументы и вычисляет квадрат первого.
И если мы передали слишком мало аргументов, этим отсутствующим параметрам будет присвоено значение undefined
, а не выдано сообщение об ошибке.
Обратной стороной этого является, конечно, то, что когда вы случайно сделаете ошибку, вам об этом никто не скажет. Таким образом, хотя технически это работает, вы никогда не должны полагаться на это, это может дать вам неожиданные результаты. Вместо этого вы всегда должны следить за тем, сколько параметров вам нужно и сколько аргументов вы передаете функции.
Параметры покоя
Однако что, если вы не знаете, сколько параметров вам нужно? Например, вы разрабатываете функцию, которая находит максимальное число в ряду чисел, но вы не знаете, сколько чисел в ряду, поэтому вам нужно разработать функцию, которая принимает любое количество аргументов.
Чтобы написать такую функцию, вам нужно поставить три точки перед последним параметром функции:
function max(...numbers) {
let result = -Infinity;
for (let number of numbers) {
if (number > result) {
result = number;
}
}
return result;
}
max(1, 2, 3, 4, 5, 6, 7);
Теперь номера параметров (он называется остальным параметром) будут привязаны к массиву, и функция вернет максимальное число в этом массиве.
Массив — это список элементов, в данном случае у нас есть [ 1, 2, 3, 4, 5, 6, 7 ]
, а for (let number of numbers
) — это то, как мы можем перебирать все элементы в этом массиве. Мы обсудим массивы в следующей статье.
Рекурсии в JavaScript
Наконец, давайте поговорим о концепции рекурсии. Рекурсия — это когда функция вызывает сама себя. Самый типичный пример — это то, как мы вычисляем степень числа.
function power(base, exponent) {
if (exponent == 0) {
return 1;
} else {
return base * power(base, exponent - 1);
}
}
Обратите внимание, что в строке 5 функция power()
вызвала себя с параметрами base
и exponent - 1
. Я знаю, что это немного сбивает с толку, но не волнуйтесь, чтобы понять этот код, давайте подставим несколько чисел. Попробуем вычислить 10^5
(10 в степени 5).
На первом этапе мы просто подставляем числа, и функция возвращает 10 * power (10, 4)
. Затем нам нужно вычислить power (10, 4)
. Подставьте числа, и мы получим 10 * power (10, 3),
что означает, что power (10, 5)
равна 10 * 10 * power (10, 3)
.
И мы продолжаем повторять те же шаги, пока не получим 10 * 10 * 10 * 10 * 10 * power (10, 0)
. Поскольку power(10, 0)
возвращает 1
, в конечном итоге мы получаем power(10, 5)
равным 10 * 10 * 10 * 10 * 10
.
Это очень элегантный способ возведения в степень, но, к сожалению, этот метод примерно в три раза медленнее, чем использование циклов в JavaScript. Это дилемма, с которой программисты сталкиваются все время: нам приходится выбирать между простотой и скоростью, потому что почти любую программу можно сделать быстрее, увеличив ее размер. Программист должен принять решение о подходящем балансе.