learnxinyminutes-docs/ru/javascript.md
2024-12-08 20:37:52 -07:00

514 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
language: JavaScript
contributors:
- ["Leigh Brenecki", "https://leigh.net.au"]
- ["Ariel Krakowski", "http://www.learneroo.com"]
filename: javascript-ru.js
translators:
- ["Alexey Gonchar", "http://github.com/finico"]
- ["Andre Polykanine", "https://github.com/Oire"]
---
JavaScript был создан в 1995 году Бренданом Айком, работавшим в компании Netscape.
Изначально он был задуман как простой язык сценариев для веб-сайтов, дополняющий
Java для более сложных веб-приложений, но его тесная интеграция с веб-страницами
и встроенная поддержка браузерами привели к тому, что он стал более распространённым,
чем Java в веб-интерфейсах.
JavaScript не ограничивается только веб-браузером: например, Node.js, программная
платформа, позволяющая выполнять JavaScript, основанная на движке V8 от браузера
Google Chrome, становится все более популярной.
```js
// Си-подобные комментарии. Однострочные комментарии начинаются с двух символов слэш,
/* а многострочные комментарии начинаются с последовательности слэш-звёздочка
и заканчиваются символами звёздочка-слэш */
// Инструкции могут заканчиваться точкой с запятой ;
doStuff();
// ... но она необязательна, так как точки с запятой автоматически вставляются
// везде, где есть символ новой строки, за некоторыми исключениями.
doStuff()
// Так как эти исключения могут привести к неожиданным результатам, мы будем всегда
// использовать точку с запятой в этом руководстве.
///////////////////////////////////
// 1. Числа, Строки и Операторы
// В JavaScript только один тип числа (64-bit IEEE 754 double).
// Он имеет 52-битную мантиссу, которой достаточно для хранения целых чисел
// с точностью вплоть до 9✕10¹⁵.
3; // = 3
1.5; // = 1.5
// Некоторые простые арифметические операции работают так, как вы ожидаете.
1 + 1; // = 2
0.1 + 0.2; // = 0.30000000000000004 (а некоторые - нет)
8 - 1; // = 7
10 * 2; // = 20
35 / 5; // = 7
// Включая деление с остатком.
5 / 2; // = 2.5
// Побитовые операции также имеются; когда вы проводите такую операцию,
// ваше число с плавающей запятой переводится в целое со знаком
// длиной *до* 32 разрядов.
1 << 2; // = 4
// Приоритет в выражениях можно явно задать скобками.
(1 + 3) * 2; // = 8
// Есть три специальных значения, которые не являются реальными числами:
Infinity; // "бесконечность", например, результат деления на 0
-Infinity; // "минус бесконечность", результат деления отрицательного числа на 0
NaN; // "не число", например, результат деления 0/0
// Существует также логический тип.
true;
false;
// Строки создаются при помощи двойных или одинарных кавычек.
'абв';
"Привет, мир!";
// Для логического отрицания используется восклицательный знак.
!true; // = false
!false; // = true
// Строгое равенство ===
1 === 1; // = true
2 === 1; // = false
// Строгое неравенство !==
1 !== 1; // = false
2 !== 1; // = true
// Другие операторы сравнения
1 < 10; // = true
1 > 10; // = false
2 <= 2; // = true
2 >= 2; // = true
// Строки объединяются при помощи оператора +
"привет, " + "мир!"; // = "Привет, мир!"
// и сравниваются при помощи < и >
"a" < "b"; // = true
// Проверка равенства с приведением типов осуществляется двойным символом равно
"5" == 5; // = true
null == undefined; // = true
// ...если только не использовать ===
"5" === 5; // = false
null === undefined; // = false
// ...приведение типов может привести к странному поведению...
13 + !0; // 14
"13" + !0; // '13true'
// Вы можете получить доступ к любому символу строки, используя метод charAt
"Это строка".charAt(0); // = 'Э'
// ...или используйте метод substring, чтобы получить более крупные части
"Привет, мир".substring(0, 6); // = "Привет"
// length - это свойство, для его получения не нужно использовать ()
"Привет".length; // = 6
// Также есть null и undefined
null; // Намеренное отсутствие значения
undefined; // используется для обозначения переменных, не имеющих
// присвоенного значения (хотя непосредственно undefined
// является значением)
// false, null, undefined, NaN, 0 и "" — это ложь; всё остальное - истина.
// Следует отметить, что 0 — это ложь, а "0" — истина, несмотря на то, что
// 0 == "0".
///////////////////////////////////
// 2. Переменные, Массивы и Объекты
// Переменные объявляются при помощи ключевого слова var. JavaScript — язык с
// динамической типизацией, поэтому не нужно явно указывать тип. Для присваивания
// значения переменной используется символ =
var someVar = 5;
// если вы пропустите слово var, вы не получите сообщение об ошибке, ...
someOtherVar = 10;
// ...но ваша переменная будет создана в глобальном контексте, а не в текущем,
// где вы ее объявили.
// Переменным, объявленным без присвоения, устанавливается значение undefined.
var someThirdVar; // = undefined
// У математических операций есть сокращённые формы:
someVar += 5; // как someVar = someVar + 5; someVar теперь имеет значение 10
someVar *= 10; // теперь someVar имеет значение 100
// Ещё более краткая запись увеличения и уменьшения на единицу:
someVar++; // теперь someVar имеет значение 101
someVar--; // вернулись к 100
// Массивы — это нумерованные списки, содержащие значения любого типа.
var myArray = ["Привет", 45, true];
// Их элементы могут быть доступны при помощи синтаксиса с квадратными скобками.
// Индексы массивов начинаются с нуля.
myArray[1]; // = 45
// Массивы можно изменять, как и их длину,
myArray.push("Мир");
myArray.length; // = 4
// добавлять и редактировать определённый элемент
myArray[3] = "Привет";
// Объекты в JavaScript похожи на словари или ассоциативные массивы в других
// языках: неупорядоченный набор пар ключ-значение.
var myObj = {key1: "Привет", key2: "Мир"};
// Ключи — это строки, но кавычки необязательны, если строка удовлетворяет
// ограничениям для имён переменных. Значения могут быть любых типов.
var myObj = {myKey: "myValue", "my other key": 4};
// Атрибуты объектов можно также получить, используя квадратные скобки
myObj["my other key"]; // = 4
// или через точку, при условии, что ключ является допустимым идентификатором.
myObj.myKey; // = "myValue"
// Объекты изменяемы; можно изменять значения и добавлять новые ключи.
myObj.myThirdKey = true;
// Если вы попытаетесь получить доступ к несуществующему значению,
// вы получите undefined.
myObj.myFourthKey; // = undefined
///////////////////////////////////
// 3. Логика и управляющие конструкции.
// Синтаксис для этого раздела почти такой же, как в Java.
// Условная конструкция работает, как и следовало ожидать,
var count = 1;
if (count == 3) {
// выполняется, если count равен 3
} else if (count == 4) {
// выполняется, если count равен 4
} else {
// выполняется, если не 3 и не 4
}
// ...как и цикл while.
while (true){
// Бесконечный цикл!
}
// Цикл do-while такой же, как while, но он всегда выполняется хотя бы раз.
var input
do {
input = getInput();
} while (!isValid(input))
// цикл for такой же, как в C и Java:
// инициализация; условие; шаг.
for (var i = 0; i < 5; i++) {
// выполнится 5 раз
}
// && — это логическое И, || — это логическое ИЛИ
if (house.size == "big" && house.color == "blue") {
house.contains = "bear";
}
if (color == "red" || color == "blue") {
// цвет красный или синий
}
// && и || используют сокращённое вычисление, что полезно
// для задания значений по умолчанию.
var name = otherName || "default";
// Оператор switch выполняет проверку на равенство при помощи ===
// используйте break, чтобы прервать выполнение после каждого case,
// или выполнение пойдёт далее даже после правильного варианта.
grade = 4;
switch (grade) {
case 5:
console.log("Отлично");
break;
case 4:
console.log("Хорошо");
break;
case 3:
console.log("Можете и лучше");
break;
default:
console.log("Ой-вей!");
break;
}
///////////////////////////////////
// 4. Функции, Область видимости и Замыкания
// Функции в JavaScript объявляются при помощи ключевого слова function.
function myFunction(thing) {
return thing.toUpperCase();
}
myFunction("foo"); // = "FOO"
// Обратите внимание, что значение, которое будет возвращено, должно начинаться
// на той же строке, что и ключевое слово return, в противном случае вы будете
// всегда возвращать undefined по причине автоматической вставки точки с запятой.
// Следите за этим при использовании стиля форматирования Allman.
function myFunction()
{
return // <- здесь точка с запятой вставится автоматически
{
thisIsAn: 'object literal'
}
}
myFunction(); // = undefined
// В JavaScript функции — это объекты первого класса, поэтому они могут быть
// присвоены различным именам переменных и передаваться другим функциям
// в качестве аргументов, например, когда назначается обработчик события:
function myFunction() {
// этот код будет вызван через 5 секунд
}
setTimeout(myFunction, 5000);
// Примечание: setTimeout не является частью языка, но реализован в браузерах и Node.js
// Функции не обязательно должны иметь имя при объявлении — вы можете написать
// анонимное определение функции непосредственно в аргументе другой функции.
setTimeout(function() {
// этот код будет вызван через 5 секунд
}, 5000);
// В JavaScript есть область видимости; функции имеют свою область
// видимости, а другие блоки — нет.
if (true) {
var i = 5;
}
i; // = 5, а не undefined, как ожидалось бы в языках с блочной областью видимости
// Это привело к общепринятому шаблону "самозапускающихся анонимных функций",
// которые препятствуют проникновению переменных в глобальную область видимости
(function() {
var temporary = 5;
// Мы можем получить доступ к глобальной области для записи в «глобальный объект»,
// который в веб-браузере всегда window. Глобальный объект может иметь другое
// имя в таких платформах, как Node.js
window.permanent = 10;
})();
temporary; // вызовет сообщение об ошибке с типом ReferenceError
permanent; // = 10
// Одной из самых мощных возможностей JavaScript являются замыкания. Если функция
// определена внутри другой функции, то внутренняя функция имеет доступ к
// переменным внешней функции даже после того, как контекст выполнения выйдет из
// внешней функции.
function sayHelloInFiveSeconds(name) {
var prompt = "Привет, " + name + "!";
// Внутренние функции по умолчанию помещаются в локальную область видимости,
// как если бы они были объявлены с помощью var.
function inner() {
alert(prompt);
}
setTimeout(inner, 5000);
// setTimeout асинхронна, поэтому функция sayHelloInFiveSeconds сразу выйдет,
// после чего setTimeout вызовет функцию inner. Однако поскольку функция inner
// «замкнута» вокруг sayHelloInFiveSeconds, она по-прежнему имеет доступ к переменной prompt
// на то время, когда она наконец будет вызвана.
}
sayHelloInFiveSeconds("Адам"); // Через 5 с откроется окно «Привет, Адам!»
///////////////////////////////////
// 5. Подробнее об объектах; Конструкторы и Прототипы
// Объекты могут содержать в себе функции.
var myObj = {
myFunc: function() {
return "Привет, мир!";
}
};
myObj.myFunc(); // = "Привет, мир!"
// Когда вызываются функции, прикреплённые к объекту, они могут получить доступ
// к этому объекту с помощью ключевого слова this.
myObj = {
myString: "Привет, мир!",
myFunc: function() {
return this.myString;
}
};
myObj.myFunc(); // = "Привет, мир!"
// Значение this зависит от того, как функция вызывается,
// а не от того, где она определена. Таким образом, наша функция не работает,
// если она вызывается не в контексте объекта.
var myFunc = myObj.myFunc;
myFunc(); // = undefined
// И наоборот, функция может быть присвоена объекту и получать доступ к нему
// через this, даже если она не была прикреплена к нему при объявлении.
var myOtherFunc = function() {
return this.myString.toUpperCase();
}
myObj.myOtherFunc = myOtherFunc;
myObj.myOtherFunc(); // = "ПРИВЕТ, МИР!"
// Мы можем также указать контекст для выполнения функции при её вызове,
// используя call или apply.
var anotherFunc = function(s) {
return this.myString + s;
}
anotherFunc.call(myObj, " И привет, Луна!"); // = "Привет, мир! И привет, Луна!"
// Функция apply почти такая же, но принимает в качестве списка аргументов массив.
anotherFunc.apply(myObj, [" И привет, Солнце!"]); // = "Привет, мир! И привет, Солнце!"
// Это полезно при работе с функцией, которая принимает последовательность
// аргументов, а вы хотите передать массив.
Math.min(42, 6, 27); // = 6
Math.min([42, 6, 27]); // = NaN (Ой-ой!)
Math.min.apply(Math, [42, 6, 27]); // = 6
// Но call и apply — только временные. Когда мы хотим связать функцию с объектом,
// мы можем использовать bind.
var boundFunc = anotherFunc.bind(myObj);
boundFunc(" И привет, Сатурн!"); // = "Привет, мир! И привет, Сатурн!"
// Bind также может использоваться для частичного применения (каррирования) функции
var product = function(a, b) { return a * b; }
var doubler = product.bind(this, 2);
doubler(8); // = 16
// Когда вы вызываете функцию с помощью ключевого слова new, создается новый объект,
// доступный функции при помощи this. Такие функции называют конструкторами.
var MyConstructor = function() {
this.myNumber = 5;
}
myNewObj = new MyConstructor(); // = {myNumber: 5}
myNewObj.myNumber; // = 5
// У каждого объекта в JavaScript есть прототип. Когда вы хотите получить
// доступ к свойству объекта, которое не существует в этом объекте, интерпретатор
// будет искать это свойство в прототипе.
// Некоторые реализации языка позволяют получить доступ к прототипу объекта
// через «магическое» свойство __proto__. Несмотря на то, что это может быть полезно
// для понимания прототипов, это не часть стандарта; мы увидим стандартные способы
// использования прототипов позже.
var myObj = {
myString: "Привет, мир!"
};
var myPrototype = {
meaningOfLife: 42,
myFunc: function() {
return this.myString.toLowerCase()
}
};
myObj.__proto__ = myPrototype;
myObj.meaningOfLife; // = 42
// Для функций это тоже работает.
myObj.myFunc(); // = "привет, мир!"
// Если интерпретатор не найдёт свойство в прототипе, то продожит поиск
// в прототипе прототипа и так далее.
myPrototype.__proto__ = {
myBoolean: true
};
myObj.myBoolean; // = true
// Здесь не участвует копирование; каждый объект хранит ссылку на свой прототип.
// Это означает, что мы можем изменить прототип, и наши изменения будут отражены везде.
myPrototype.meaningOfLife = 43;
myObj.meaningOfLife; // = 43
// Мы упомянули, что свойство __proto__ нестандартно, и нет никакого стандартного
// способа, чтобы изменить прототип существующего объекта. Однако есть два
// способа создать новый объект с заданным прототипом.
// Первый способ — это Object.create, который появился в JavaScript недавно,
// а потому доступен ещё не во всех реализациях языка.
var myObj = Object.create(myPrototype);
myObj.meaningOfLife; // = 43
// Второй способ, который работает везде, имеет дело с конструкторами.
// У конструкторов есть свойство с именем prototype. Это *не* прототип
// функции-конструктора; напротив, это прототип для новых объектов, которые
// будут созданы с помощью этого конструктора и ключевого слова new.
MyConstructor.prototype = {
myNumber: 5,
getMyNumber: function() {
return this.myNumber;
}
};
var myNewObj2 = new MyConstructor();
myNewObj2.getMyNumber(); // = 5
myNewObj2.myNumber = 6
myNewObj2.getMyNumber(); // = 6
// У встроенных типов, таких, как строки и числа, также есть конструкторы, которые
// создают эквивалентные объекты-обёртки.
var myNumber = 12;
var myNumberObj = new Number(12);
myNumber == myNumberObj; // = true
// За исключением того, что они не в точности равны.
typeof myNumber; // = 'number'
typeof myNumberObj; // = 'object'
myNumber === myNumberObj; // = false
if (0) {
// Этот код не выполнится, потому что 0 - это ложь.
}
// Впрочем, объекты-обёртки и встроенные типы имеют общие прототипы,
// поэтому вы можете расширить функциональность строк, например:
String.prototype.firstCharacter = function() {
return this.charAt(0);
}
"abc".firstCharacter(); // = "a"
// Это часто используется в т.н. полифилах, которые реализуют новые возможности
// JavaScript в старой реализации языка, так что они могут быть использованы в
// старых средах, таких, как устаревшие браузеры.
// Например, мы упомянули, что Object.create доступен не во всех реализациях, но
// мы сможем использовать его с помощью такого полифила:
if (Object.create === undefined) { // не перезаписываем метод, если он существует
Object.create = function(proto) {
// создаём временный конструктор с правильным прототипом
var Constructor = function(){};
Constructor.prototype = proto;
// затем используем его для создания нового,
// правильно прототипированного объекта
return new Constructor();
}
}
```
## Что ещё почитать
[Современный учебник JavaScript (Илья Кантор)](http://learn.javascript.ru) —
качественный учебник по JavaScript на русском языке.
[Mozilla Developer Network](https://developer.mozilla.org/ru/docs/Web/JavaScript) —
предоставляет отличную документацию для JavaScript, как он используется в браузерах.
Кроме того, это вики. Поэтому, если вы знаете больше, вы можете помочь другим,
делясь своими знаниями.
[JavaScript Garden](https://shamansir.github.io/JavaScript-Garden/ru/) — это
подробное руководство по всем неинтуитивным особенностей языка.
[Stack Overflow](https://stackoverflow.com/questions/tagged/javascript) — можно
найти ответ почти на любой ваш вопрос, а если его нет, то задать вопрос самому.