Skip to content

Commit da43fb3

Browse files
committed
Merge branch 'ru-translation' of https://github.com/shamansir/JavaScript-Garden into russian-translation
2 parents 3a86bd3 + 23dcbad commit da43fb3

29 files changed

+1599
-1
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@
22
/build
33
/html
44
/site/de
5+
/site/ru
6+
*.md~
7+
*.src.md

doc/language.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
22
"default": "en",
3-
"listed": ["en"]
3+
"listed": ["en", "ru"]
44
}
5+

doc/ru/appendix/fromtranslators.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
## От переводчиков
2+
3+
Авторы этой документации требуют от читателя не совершать каких-либо ошибок и постоянно следить за качеством пишущегося кода. Мы, как переводчики и опытные программисты на JavaScript рекомендуем *прислушиваться* к этим советам, но при этом не делать из этого *крайность*. Опыт — сын ошибок трудных, и иногда в борьбе с ошибками зарождается намного более детальное понимание предмета. Да, нужно избегать ошибок, но допускать их неосознанно — вполне нормально.
4+
5+
К примеру, в статье про [сравнение объектов](#types.equality) авторы настоятельно рекомендуют использовать *только* оператор строгого неравенства `===`. Но мы считаем, что если вы уверены и осознали, что оба сравниваемых операнда имеют один тип, вы имеете право опустить последний символ `=`. Вы вольны применять строгое неравенство только в случаях, когда вы не уверены в типах операндов (`!== undefined` — это полезный приём). Так в вашем коде будут опасные и безопасные области, но при этом по коду будет явно видно, где вы рассчитываете на переменные одинаковых типов, а где позволяете пользователю вольности.
6+
7+
Функцию [`setInterval`](#other.timeouts) тоже можно использовать, если вы стопроцентно уверены, что код внутри неё будет исполняться как минимум в три раза быстрее переданного ей интервала.
8+
9+
С другой стороны, [использование `var`](#function.scopes) и грамотная [расстановка точек с запятой](#core.semicolon) — обязательные вещи, халатное отношение к которым никак не может быть оправдано — в осознанном пропуске `var` (если только вы не переопределяете глобальный объект браузера... хотя *зачем*?) или точки с запятой нет никакого смысла.
10+
11+
Относитесь с **мудростью** к тому, что вы пишете — *важно* знать как работает именно ваш код и как это соответствует приведённым в статье тезисам — и уже из этого вы сможете делать вывод, подходит ли вам тот или иной подход или нет. *Важно* знать как работает [прототипное наследование](#object.prototype), но это не так необходимо, если вы используете функциональный подход или пользуетесь какой-либо сторонней библиотекой. Важно помнить о том, что у вас недостаёт какого-либо конкретного знания и что пробел следует заполнить, но если вы не используете в работе эту часть, вы всё равно можете писать хороший код — ну, если у вас есть талант.
12+
13+
Гонка за оптимизацией — это драматично и правильно, но лучше написать работающий и понятный вам код, а потом уже его оптимизировать и искать узкие места, при необходимости. Оптимизацию необходимо делать, если вы видите явные неудобства для пользователя в тех или иных браузерах или у вас есть супер-крупный проект, которым никогда мешает оптимизация, или вы работаете с какой-либо сверхтребовательной технологией типа WebGL. Данная документация очень поможет вам в определении этих узких мест.
14+

doc/ru/array/constructor.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
## Конструктор `Array`
2+
3+
Так как в конструкторе `Array` есть некоторая двусмысленность касающаяся его параметров, настоятельно рекомендуется при создании массивов всегда использовать синтаксис литеральной нотации — `[]`.
4+
5+
[1, 2, 3]; // Результат: [1, 2, 3]
6+
new Array(1, 2, 3); // Результат: [1, 2, 3]
7+
8+
[3]; // Результат: [3]
9+
new Array(3); // Результат: []
10+
new Array('3') // Результат: ['3']
11+
12+
В случае, когда в конструктор `Array` передаётся один аргумент и этот аргумент имеет тип `Number`, конструктор возвращает новый, *заполненный случайными значениями*, массив, имеющий длину равную значению переданного аргумента. Стоит заметить, что в этом случае будет установлено только свойство `length` нового массива, индексы массива фактически не будут проинициализированы.
13+
14+
var arr = new Array(3);
15+
arr[1]; // не определён, undefined
16+
1 in arr; // false, индекс не был установлен
17+
18+
Поведение, которое позволяет изначально установить только размер массива может пригодиться лишь в нескольких случаях, таких как повторение строк, за счёт чего избегается использование цикла `for loop`.
19+
20+
new Array(count + 1).join(stringToRepeat);
21+
22+
### Заключение
23+
24+
Использование конструктора `Array` нужно избегать, насколько это возможно. Литералы определённо предпочтительнее — это краткая запись и она имеет более понятный синтаксис, так что при этом даже улучшается читабельность кода.
25+

doc/ru/array/general.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
##  Итерации по массивам и свойства
2+
3+
Несмотря на то, что массивы в JavaScript являются объектами, нет достаточных оснований для использования [цикла `for in`](#object.forinloop) для итерации по элементам массива. Фактически, существует несколько весомых причин **против** использования `for in` в массивах.
4+
5+
> **Замечание:** Массивы в JavaScript **не** являются *ассоциативными массивами*. Для связывания ключей и значений в JavaScript есть только [объекты](#object.general). И при том, что ассоциативные массивы **сохраняют** заданный порядок, объекты **не** делают этого.
6+
7+
Во время выполнения `for in` циклически перебираются все свойства объекта, находящиеся в цепочке прототипов. Единственный способ исключить ненужные свойства — использовать [`hasOwnProperty`](#object.hasownproperty), а это **в 20 раз** медленнее обычного цикла `for`.
8+
9+
### Итерирование
10+
11+
Для достижения лучшей производительности при итерации по массивам, лучше всего использовать обычный цикл `for`.
12+
13+
var list = [1, 2, 3, 4, 5, ...... 100000000];
14+
for(var i = 0, l = list.length; i < l; i++) {
15+
console.log(list[i]);
16+
}
17+
18+
В примере выше есть один дополнительный приём, с помощью которого кэшируется величина длины массива: `l = list.length`.
19+
20+
Несмотря на то, что свойство `length` определено в самом массиве, поиск этого свойства накладывает дополнительные расходы на каждой итерации цикла. Пусть в этом случае новые движки JavaScript теоретически **могут** применить оптимизацию, но нет никакого способа узнать, будет оптимизирован код на новом движке или нет.
21+
22+
Фактически, отсутствие кэширования может привести к выполнению цикла в **два раза медленнее**, чем при кэшировании длины
23+
24+
### Свойство `length`
25+
26+
Хотя *геттер* свойства `length` просто возвращает количество элементов содежащихся в массиве, *сеттер* можно использовать для **обрезания** массива.
27+
28+
var foo = [1, 2, 3, 4, 5, 6];
29+
foo.length = 3;
30+
foo; // [1, 2, 3]
31+
32+
foo.length = 6;
33+
foo; // [1, 2, 3]
34+
35+
Присвоение свойству `length` меньшей величины урезает массив, однако присвоение большего значения не даст никакого эффекта.
36+
37+
### Заключение
38+
39+
Для оптимальной работы кода рекомендуется всегда использовать простой цикл `for` и кэшировать свойство `length`. Использование `for in` с массивами является признаком плохого кода, обладающего предпосылками к ошибкам и может привести к низкой скорости его выполнения.
40+

doc/ru/core/eval.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
## Почему нельзя использовать `eval`
2+
3+
Функция `eval` выполняет строку кода JavaScript в локальной области видимости.
4+
5+
var foo = 1;
6+
function test() {
7+
var foo = 2;
8+
eval('foo = 3');
9+
return foo;
10+
}
11+
test(); // 3
12+
foo; // 1
13+
14+
Но `eval` исполняется в локальной области видимости только тогда, когда он вызывается **напрямую** *и при этом* имя вызываемой функции именно `eval`.
15+
16+
var foo = 1;
17+
function test() {
18+
var foo = 2;
19+
var bar = eval;
20+
bar('foo = 3');
21+
return foo;
22+
}
23+
test(); // 2
24+
foo; // 3
25+
26+
**Любой ценой** избегайте использования функции `eval`. 99.9% случаев её "использования" могут достигаться **без её участия**.
27+
28+
### `eval` под прикрытием
29+
30+
Обе [функции работы с интервалами времени](#other.timeouts) `setTimeout` и `setInterval` могут принимать строку в качестве первого аргумента. Эта строка **всегда** будет выполняться в глобальной области видимости, поскольку `eval` в этом случае вызывается *не напрямую*.
31+
32+
### Проблемы с безопасностью
33+
34+
Кроме всего прочего, функция `eval` — это проблема в безопасности, поскольку исполняется **любой** переданный в неё код; **никогда** не следует использовать её со строками из неизвестных или недоверительных источников.
35+
36+
### Заключение
37+
38+
Никогда не стоит использовать `eval`: любое применение такого кода поднимает вопросы о качестве его работы, производительности и безопасности. Если вдруг для работы вам необходим `eval`, эта часть должна тут же ставиться под сомнение и **не** должна использоваться в первую очередь — необходимо найти *лучший способ* , которому не требуются вызовы `eval`.
39+

doc/ru/core/semicolon.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
## Автоматическая вставка точек с запятой
2+
3+
Хоть JavaScript и имеет синтаксис, подобный языкам семейства C, он при этом **не** принуждает вас ставить точки с запятой в исходном коде — вы всегда можете их опустить.
4+
5+
При этом JavaScript — не язык без точек с запятой, они на самом деле нужны ему, чтобы он мог разобраться в вашем коде. Поэтому парсер JavaScript **автоматически** вставляет их в те места, где сталкивается с ошибкой парсинга из-за их отсутствия.
6+
7+
var foo = function() {
8+
} // ошибка разбора, ожидается точка с запятой
9+
test()
10+
11+
Происходит вставка и парсер пытается снова.
12+
13+
var foo = function() {
14+
}; // ошибки нет, парсер продолжает
15+
test()
16+
17+
Автоматическая вставка точек с запятой считается одним из **наибольших** упущений в проекте языка, поскольку она *может* изменить поведение кода.
18+
19+
### Как это работает
20+
21+
Приведённый код не содержит точек с запятой, так что места для их вставки остаются на совести парсера:
22+
23+
(function(window, undefined) {
24+
function test(options) {
25+
log('тестируем!')
26+
27+
(options.list || []).forEach(function(i) {
28+
29+
})
30+
31+
options.value.test(
32+
'здесь передадим длинную строчку',
33+
'и ещё одну на всякий случай'
34+
)
35+
36+
return
37+
{
38+
foo: function() {}
39+
}
40+
}
41+
window.test = test
42+
43+
})(window)
44+
45+
(function(window) {
46+
window.someLibrary = {}
47+
48+
})(window)
49+
50+
Ниже представлен результат игры парсера в "угадалки".
51+
52+
(function(window, undefined) {
53+
function test(options) {
54+
55+
// не вставлена точка с запятой, строки были объединены
56+
log('тестируем!')(options.list || []).forEach(function(i) {
57+
58+
}); // <- вставлена
59+
60+
options.value.test(
61+
'здесь передадим длинную строчку',
62+
'и ещё одну на всякий случай'
63+
); // <- вставлена
64+
65+
return; // <- вставлена, в результате оператор return разбит на два блока
66+
{ // теперь парсер считает этот блок отдельным
67+
68+
// метка и одинокое выражение
69+
foo: function() {}
70+
}; // <- вставлена
71+
}
72+
window.test = test; // <- вставлена
73+
74+
// снова объединились строки
75+
})(window)(function(window) {
76+
window.someLibrary = {}; // <- вставлена
77+
78+
})(window); //<- вставлена
79+
80+
> **Замечание:** Парсер JavaScript некорректно обрабатывает оператор `return`, за которым следует новая строка; кстати, причина может быть и не в автоматической вставке точек с запятой, но это в любом случае нежелательный побочный эффект
81+
82+
Парсер радикально подменил поведение изначального кода, а в определённых случаях он сделал **абсолютно неправильные выводы**.
83+
84+
### "Висящие" скобки
85+
86+
Если парсер встречает "висящую" скобку, то он **не** вставляет точку с запятой.
87+
88+
log('тестируем!')
89+
(options.list || []).forEach(function(i) {})
90+
91+
Такой код трасформируется в строку
92+
93+
log('тестируем!')(options.list || []).forEach(function(i) {})
94+
95+
**Чрезвычайно** высоки шансы, что `log` возращает **не** функцию; таким образом, эта строка вызовет `TypeError` с сообщением о том, что `undefined не является функцией`.
96+
97+
### Заключение
98+
99+
Настоятельно рекомендуем **никогда** не забывать ставить точку с запятой; так же рекомендуется оставлять скобки на одной строке с соответствующим оператором и никогда не опускать их для выражений с использованием `if` / `else`. Оба этих совета не только повысят читабельность вашего кода, но и предотвратят от изменения поведения кода, произведённого парсером втихую.
100+

0 commit comments

Comments
 (0)