├── .gitignore
├── README.md
├── diff.md
└── linters
├── .jshintrc
└── SublimeLinter
└── SublimeLinter.sublime-settings
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | .idea/*
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Стиль написания кода на JavaScript для Uprock: Перевод и расширение [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript)
2 |
3 | *Наиболее разумный подход к JavaScript*
4 |
5 |
6 | ## Оглавление
7 |
8 | 1. [Типы](#types)
9 | 1. [Объекты](#objects)
10 | 1. [Массивы](#arrays)
11 | 1. [Строки](#strings)
12 | 1. [Функции](#functions)
13 | 1. [Свойства](#properties)
14 | 1. [Переменные](#variables)
15 | 1. [Области видимости](#hoisting)
16 | 1. [Условные выражения и равенства](#conditionals)
17 | 1. [Блоки кода](#blocks)
18 | 1. [Комментарии](#comments)
19 | 1. [Пробелы](#whitespace)
20 | 1. [Запятые](#commas)
21 | 1. [Точки с запятой](#semicolons)
22 | 1. [Приведение типов](#type-coercion)
23 | 1. [Соглашение об именовании](#naming-conventions)
24 | 1. [Геттеры и сеттеры](#accessors)
25 | 1. [Конструкторы](#constructors)
26 | 1. [События](#events)
27 | 1. [Модули](#modules)
28 | 1. [jQuery](#jquery)
29 | 1. [Совместимость с ES5](#es5)
30 | 1. [Тестирование](#testing)
31 | 1. [Быстродействие](#performance)
32 | 1. [Ресурсы](#resources)
33 | 1. [В реальном мире](#in-the-wild)
34 | 1. [Переводы](#translation)
35 | 1. [Лицензия](#license)
36 |
37 | ## Типы
38 |
39 | - **Простые типы**: Когда вы взаимодействуете с простым типом, вы взаимодействуете непосредственно с его значением в памяти.
40 |
41 | + `string`
42 | + `number`
43 | + `boolean`
44 | + `null`
45 | + `undefined`
46 |
47 | ```javascript
48 | var foo = 1,
49 | bar = foo;
50 |
51 | bar = 9;
52 |
53 | console.log(foo, bar); // => 1, 9. foo не изменился
54 | ```
55 | - **Сложные типы**: Когда вы взаимодействуете со сложным типом, вы взаимодействуете с ссылкой на его значение в памяти.
56 |
57 | + `object`
58 | + `array`
59 | + `function`
60 |
61 | ```javascript
62 | var foo = [1, 2],
63 | bar = foo;
64 |
65 | bar[0] = 9;
66 |
67 | console.log(foo[0], bar[0]); // => 9, 9.
68 | ```
69 |
70 | **[[⬆]](#Оглавление)**
71 |
72 | ## Объекты
73 |
74 | - Для создания объекта используйте фигурные скобки. Не создавайте объекты через конструктор `new Object`.
75 |
76 | ```javascript
77 | // плохо
78 | var item = new Object();
79 |
80 | // хорошо
81 | var item = {};
82 | ```
83 |
84 | - Не используйте [зарезервированные слова](http://es5.github.io/#x7.6.1) в качестве ключей объектов. Они не будут работать в IE8. [Подробнее](https://github.com/airbnb/javascript/issues/61)
85 |
86 | ```javascript
87 | // плохо
88 | var superman = {
89 | default: { clark: 'kent' },
90 | private: true
91 | };
92 |
93 | // хорошо
94 | var superman = {
95 | defaults: { clark: 'kent' },
96 | hidden: true
97 | };
98 | ```
99 |
100 | - Не используйте ключевые слова (в том числе измененные). Вместо них используйте синонимы.
101 |
102 | ```javascript
103 | // плохо
104 | var superman = {
105 | class: 'alien'
106 | };
107 |
108 | // плохо
109 | var superman = {
110 | klass: 'alien'
111 | };
112 |
113 | // хорошо
114 | var superman = {
115 | type: 'alien'
116 | };
117 | ```
118 | **[[⬆]](#Оглавление)**
119 |
120 | ## Массивы
121 |
122 | - Для создания массива используйте квадратные скобки. Не создавайте массивы через конструктор `new Array`.
123 |
124 | ```javascript
125 | // плохо
126 | var items = new Array();
127 |
128 | // хорошо
129 | var items = [];
130 | ```
131 |
132 | - Если вы не знаете длину массива, используйте Array::push.
133 |
134 | ```javascript
135 | var someStack = [];
136 |
137 |
138 | // плохо
139 | someStack[someStack.length] = 'abracadabra';
140 |
141 | // хорошо
142 | someStack.push('abracadabra');
143 | ```
144 |
145 | - Если вам необходимо скопировать массив, используйте Array::slice. [jsPerf](http://jsperf.com/converting-arguments-to-an-array/7)
146 |
147 | ```javascript
148 | var len = items.length,
149 | itemsCopy = [],
150 | i;
151 |
152 | // плохо
153 | for (i = 0; i < len; i++) {
154 | itemsCopy[i] = items[i];
155 | }
156 |
157 | // хорошо
158 | itemsCopy = items.slice();
159 | ```
160 |
161 | - Чтобы скопировать похожий по свойствам на массив объект (например, NodeList или Arguments), используйте Array::slice.
162 |
163 | ```javascript
164 | function trigger() {
165 | var args = Array.prototype.slice.call(arguments);
166 | ...
167 | }
168 | ```
169 |
170 | **[[⬆]](#Оглавление)**
171 |
172 |
173 | ## Строки
174 |
175 | - Используйте одинарные кавычки `''` для строк.
176 |
177 | ```javascript
178 | // плохо
179 | var name = "Боб Дилан";
180 |
181 | // хорошо
182 | var name = 'Боб Дилан';
183 |
184 | // плохо
185 | var fullName = "Боб " + this.lastName;
186 |
187 | // хорошо
188 | var fullName = 'Дилан ' + this.lastName;
189 | ```
190 |
191 | - Строки длиннее 80 символов нужно разделять, выполняя перенос через конкатенацию строк.
192 | - Осторожно: строки с большим количеством конкатенаций могут отрицательно влиять на быстродействие. [jsPerf](http://jsperf.com/ya-string-concat) и [Обсуждение](https://github.com/airbnb/javascript/issues/40)
193 |
194 | ```javascript
195 | // плохо
196 | var errorMessage = 'Эта сверхдлинная ошибка возникла из-за белой обезъяны. Не говори про обезъяну! Не слушай об обезьяне! Не думай об обезъяне!';
197 |
198 | // плохо
199 | var errorMessage = 'Эта сверхдлинная ошибка возникла из-за белой обезъяны. \
200 | Не говори про обезъяну! Не слушай об обезьяне! \
201 | Не думай об обезъяне!';
202 |
203 | // хорошо
204 | var errorMessage = 'Эта сверхдлинная ошибка возникла из-за белой обезъяны. ' +
205 | 'Не говори про обезъяну! Не слушай об обезьяне! ' +
206 | 'Не думай об обезъяне!';
207 | ```
208 |
209 | - Когда строка создается программным путем, используйте Array::join вместо объединения строк. В основном для IE: [jsPerf](http://jsperf.com/string-vs-array-concat/2).
210 |
211 | ```javascript
212 | var items,
213 | messages,
214 | length,
215 | i;
216 |
217 | messages = [{
218 | state: 'success',
219 | message: 'Это работает.'
220 | },{
221 | state: 'success',
222 | message: 'Это тоже.'
223 | },{
224 | state: 'error',
225 | message: 'А я томат.'
226 | }];
227 |
228 | length = messages.length;
229 |
230 | // плохо
231 | function inbox(messages) {
232 | items = '
';
233 |
234 | for (i = 0; i < length; i++) {
235 | items += '- ' + messages[i].message + '
';
236 | }
237 |
238 | return items + '
';
239 | }
240 |
241 | // хорошо
242 | function inbox(messages) {
243 | items = [];
244 |
245 | for (i = 0; i < length; i++) {
246 | items[i] = messages[i].message;
247 | }
248 |
249 | return '';
250 | }
251 | ```
252 |
253 | **[[⬆]](#Оглавление)**
254 |
255 |
256 | ## Функции
257 |
258 | - Объявление функций:
259 |
260 | ```javascript
261 | // объявление анонимной функции
262 | var anonymous = function() {
263 | return true;
264 | };
265 |
266 | // объявление именованной функции
267 | var named = function named() {
268 | return true;
269 | };
270 |
271 | // объявление функции, которая сразу же выполняется (замыкание)
272 | (function() {
273 | console.log('Если вы читаете это, вы открыли консоль.');
274 | })();
275 | ```
276 | - Никогда не объявляйте функцию внутри блока кода — например в if, while, else и так далее. Единственное исключение — блок функции. Вместо этого присваивайте функцию уже объявленной через `var` переменной. Условное объявление функций работает, но в различных браузерах работает по-разному.
277 | - **Примечание** ECMA-262 устанавливает понятие `блока` как списка операторов. Объявление функции (не путайте с присвоением функции переменной) не является оператором. [Комментарий по этому вопросу в ECMA-262](http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf#page=97).
278 |
279 | ```javascript
280 | // плохо
281 | if (currentUser) {
282 | function test() {
283 | console.log('Плохой мальчик.');
284 | }
285 | }
286 |
287 | // хорошо
288 | var test;
289 | if (currentUser) {
290 | test = function test() {
291 | console.log('Молодец.');
292 | };
293 | }
294 | ```
295 |
296 | - Никогда не используйте аргумент функции `arguments`, он будет более приоритетным над объектом `arguments`, который доступен без объявления для каждой функции.
297 |
298 | ```javascript
299 | // плохо
300 | function nope(name, options, arguments) {
301 | // ...код...
302 | }
303 |
304 | // хорошо
305 | function yup(name, options, args) {
306 | // ...код...
307 | }
308 | ```
309 |
310 | **[[⬆]](#Оглавление)**
311 |
312 |
313 |
314 | ## Свойства
315 |
316 | - Используйте точечную нотацию для доступа к свойствам и методам.
317 |
318 | ```javascript
319 | var luke = {
320 | jedi: true,
321 | age: 28
322 | };
323 |
324 | // плохо
325 | var isJedi = luke['jedi'];
326 |
327 | // хорошо
328 | var isJedi = luke.jedi;
329 | ```
330 |
331 | - Используйте нотацию с `[]`, когда вы получаете свойство, имя для которого хранится в переменной.
332 |
333 | ```javascript
334 | var luke = {
335 | jedi: true,
336 | age: 28
337 | };
338 |
339 | function getProp(prop) {
340 | return luke[prop];
341 | }
342 |
343 | var isJedi = getProp('jedi');
344 | ```
345 |
346 | **[[⬆]](#Оглавление)**
347 |
348 |
349 | ## Переменные
350 |
351 | - Всегда используйте `var` для объявления переменных. В противном случае переменная будет объявлена глобальной. Загрязнение глобального пространства имен — всегда плохо.
352 |
353 | ```javascript
354 | // плохо
355 | superPower = new SuperPower();
356 |
357 | // хорошо
358 | var superPower = new SuperPower();
359 | ```
360 |
361 | - Используйте одно `var` объявление переменных для всех переменных, и объявляйте каждую переменную на новой строке.
362 |
363 | ```javascript
364 | // плохо
365 | var items = getItems();
366 | var goSportsTeam = true;
367 | var dragonball = 'z';
368 |
369 | // хорошо
370 | var items = getItems(),
371 | goSportsTeam = true,
372 | dragonball = 'z';
373 | ```
374 |
375 | - Объявляйте переменные, которым не присваивается значение, в конце. Это удобно, когда вам необходимо задать значение одной из этих переменных на базе уже присвоенных значений.
376 |
377 | ```javascript
378 | // плохо
379 | var i, len, dragonball,
380 | items = getItems(),
381 | goSportsTeam = true;
382 |
383 | // плохо
384 | var i, items = getItems(),
385 | dragonball,
386 | goSportsTeam = true,
387 | len;
388 |
389 | // хорошо
390 | var items = getItems(),
391 | goSportsTeam = true,
392 | dragonball,
393 | length,
394 | i;
395 | ```
396 |
397 | - Присваивайте переменные в начале области видимости. Это помогает избегать проблем с объявлением переменных и областями видимости.
398 |
399 | ```javascript
400 | // плохо
401 | function() {
402 | test();
403 | console.log('делаю что-нибудь..');
404 |
405 | //..или не делаю...
406 |
407 | var name = getName();
408 |
409 | if (name === 'test') {
410 | return false;
411 | }
412 |
413 | return name;
414 | }
415 |
416 | // хорошо
417 | function() {
418 | var name = getName();
419 |
420 | test();
421 | console.log('делаю что-то полезное..');
422 |
423 | //..продолжаю приносить пользу людям..
424 |
425 | if (name === 'test') {
426 | return false;
427 | }
428 |
429 | return name;
430 | }
431 |
432 | // плохо
433 | function() {
434 | var name = getName();
435 |
436 | if (!arguments.length) {
437 | return false;
438 | }
439 |
440 | return true;
441 | }
442 |
443 | // хорошо
444 | function() {
445 | if (!arguments.length) {
446 | return false;
447 | }
448 |
449 | var name = getName();
450 |
451 | return true;
452 | }
453 | ```
454 |
455 | **[[⬆]](#Оглавление)**
456 |
457 |
458 | ## Области видимости
459 |
460 | - Объявление переменных ограничивается областью видимости, а присвоение — нет.
461 |
462 | ```javascript
463 | // Мы знаем, что это не будет работать
464 | // если нет глобальной переменной notDefined
465 | function example() {
466 | console.log(notDefined); // => выбрасывает код с ошибкой ReferenceError
467 | }
468 |
469 | // Декларирование переменной после ссылки на нее
470 | // не будет работать из-за ограничения области видимости.
471 | function example() {
472 | console.log(declaredButNotAssigned); // => undefined
473 | var declaredButNotAssigned = true;
474 | }
475 |
476 | // Интерпретатор переносит объявление переменной
477 | // к верху области видимости.
478 | // Что значит, что предыдущий пример в действительности
479 | // будет воспринят интерпретатором так:
480 | function example() {
481 | var declaredButNotAssigned;
482 | console.log(declaredButNotAssigned); // => undefined
483 | declaredButNotAssigned = true;
484 | }
485 | ```
486 |
487 | - Объявление анонимной функции поднимает наверх области видимости саму переменную, но не ее значение.
488 |
489 | ```javascript
490 | function example() {
491 | console.log(anonymous); // => undefined
492 |
493 | anonymous(); // => TypeError anonymous is not a function
494 | // Ошибка типов: переменная anonymous не является функцией и не может быть вызвана
495 |
496 | var anonymous = function() {
497 | console.log('анонимная функция');
498 | };
499 | }
500 | ```
501 |
502 | - Именованные функции поднимают наверх области видимости переменную, не ее значение. Имя функции при этом недоступно в области видимости переменной и доступно только изнутри.
503 |
504 | ```javascript
505 | function example() {
506 | console.log(named); // => undefined
507 |
508 | named(); // => TypeError named is not a function
509 | // Ошибка типов: переменная named не является функцией и не может быть вызвана
510 |
511 | superPower(); // => ReferenceError superPower is not defined (Ошибка ссылки: переменная superPower не найдена в этой области видимости)
512 |
513 | var named = function superPower() {
514 | console.log('Я лечууууу');
515 | };
516 | }
517 |
518 | // То же самое происходит, когда имя функции и имя переменной совпадают.
519 | // var named доступно изнутри области видимости функции example.
520 | // function named доступна только изнутри ее самой.
521 | function example() {
522 | console.log(named); // => undefined
523 |
524 | named(); // => TypeError named is not a function
525 | // Ошибка типов: переменная named не является функцией и не может быть вызвана
526 |
527 | var named = function named() {
528 | console.log('именованная функция');
529 | }
530 | }
531 | ```
532 |
533 | - Объявления функции поднимают на верх текущей области видимости и имя, и свое значение.
534 |
535 | ```javascript
536 | function example() {
537 | superPower(); // => Я лечууууу
538 |
539 | function superPower() {
540 | console.log('Я лечууууу');
541 | }
542 | }
543 | ```
544 |
545 | - Более подробно можно прочитать в статье [JavaScript Scoping & Hoisting](http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting) от [Ben Cherry](http://www.adequatelygood.com/)
546 |
547 | **[[⬆]](#Оглавление)**
548 |
549 |
550 |
551 | ## Условные выражения и равенства
552 |
553 | - Используйте `===` и `!==` вместо `==` и `!=`.
554 | - Условные выражения вычисляются посредством приведения к логическому типу Boolean через метод `ToBoolean` и всегда следуют следующим правилам:
555 |
556 | + **Object** всегда соответствует **true**
557 | + **Undefined** всегда соответствует **false**
558 | + **Null** всегда соответствует **false**
559 | + **Boolean** остается неизменным
560 | + **Number** соответствует **false**, если является **+0, -0, или NaN**, в противном случае соответствует **true**
561 | + **String** означает **false**, если является пустой строкой `''`, в противном случае **true**. Условно говоря, для строки происходит сравнение не ее самой, а ее длины – в соответствии с типом number.
562 |
563 | ```javascript
564 | if ([0]) {
565 | // true
566 | // Массив(Array) является объектом, объекты преобразуются в true
567 | }
568 | ```
569 |
570 | - Используйте короткий синтаксис.
571 |
572 | ```javascript
573 | // плохо
574 | if (name !== '') {
575 | // ...код...
576 | }
577 |
578 | // хорошо
579 | if (name) {
580 | // ...код...
581 | }
582 |
583 | // плохо
584 | if (collection.length > 0) {
585 | // ...код...
586 | }
587 |
588 | // хорошо
589 | if (collection.length) {
590 | // ...код...
591 | }
592 | ```
593 |
594 | - Более подробно можно прочитать в статье [Truth Equality and JavaScript](http://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/#more-2108) от Angus Croll
595 |
596 | **[[⬆]](#Оглавление)**
597 |
598 |
599 | ## Блоки кода
600 |
601 | - Используйте фигурные скобки для всех многострочных блоков.
602 |
603 | ```javascript
604 | // плохо
605 | if (test)
606 | return false;
607 |
608 | // хорошо
609 | if (test) return false;
610 |
611 | // хорошо
612 | if (test) {
613 | return false;
614 | }
615 |
616 | // плохо
617 | function() { return false; }
618 |
619 | // хорошо
620 | function() {
621 | return false;
622 | }
623 | ```
624 |
625 | **[[⬆]](#Оглавление)**
626 |
627 |
628 | ## Комментарии
629 |
630 | - Используйте `/** ... */` для многострочных комментариев. Включите описание, опишите типы и значения для всех параметров и возвращаемых значений в формате jsdoc.
631 |
632 | ```javascript
633 | // плохо
634 | // make() возвращает новый элемент
635 | // основываясь на получаемом имени тэга
636 | //
637 | // @param tag
638 | // @return element
639 | function make(tag) {
640 |
641 | // ...создаем element...
642 |
643 | return element;
644 | }
645 |
646 | // хорошо
647 | /**
648 | * make() возвращает новый элемент
649 | * основываясь на получаемом имени тэга
650 | *
651 | * @param tag
652 | * @return element
653 | */
654 | function make(tag) {
655 |
656 | // ...создаем element...
657 |
658 | return element;
659 | }
660 | ```
661 |
662 | - Используйте `//` для комментариев в одну строку. Размещайте комментарии на новой строке над темой комментария. Добавляйте пустую строку над комментарием.
663 |
664 | ```javascript
665 | // плохо
666 | var active = true; // устанавливаем активным элементом
667 |
668 | // хорошо
669 | // устанавливаем активным элементом
670 | var active = true;
671 |
672 | // плохо
673 | function getType() {
674 | console.log('проверяем тип...');
675 | // задаем тип по умолчанию 'no type'
676 | var type = this._type || 'no type';
677 |
678 | return type;
679 | }
680 |
681 | // хорошо
682 | function getType() {
683 | console.log('проверяем тип...');
684 |
685 | // задаем тип по умолчанию 'no type'
686 | var type = this._type || 'no type';
687 |
688 | return type;
689 | }
690 | ```
691 |
692 | - Префикс `TODO` помогает другим разработчикам быстро понять, что вы указываете на проблему, к которой нужно вернуться в дальнейшем, или если вы предлагете решение проблемы, которое должно быть реализовано. Эти комментарии отличаются от обычных комментариев, так как не описывают текущее поведение, а призывают к действию, например `TODO -- нужно реализовать интерфейс`. Такие комментарии также автоматически обнаруживаются многими IDE и редакторами кода, что позволяет быстро перемещаться между ними.
693 |
694 | - Используйте `// TODO FIXME:` для аннотирования проблем
695 |
696 | ```javascript
697 | function Calculator() {
698 |
699 | // TODO FIXME: тут не нужно использовать глобальную переменную
700 | total = 0;
701 |
702 | return this;
703 | }
704 | ```
705 |
706 | - Используйте `// TODO:` для указания решений проблем
707 |
708 | ```javascript
709 | function Calculator() {
710 |
711 | // TODO: должна быть возможность изменять значение через параметр функции
712 | this.total = 0;
713 |
714 | return this;
715 | }
716 | ```
717 |
718 | **[[⬆]](#Оглавление)**
719 |
720 |
721 | ## Пробелы
722 |
723 | - Используйте программную табуляцию (ее поддерживают все современные редакторы кода и IDE) из двух пробелов.
724 |
725 | ```javascript
726 | // плохо
727 | function() {
728 | ∙∙∙∙var name;
729 | }
730 |
731 | // плохо
732 | function() {
733 | ∙var name;
734 | }
735 |
736 | // хорошо
737 | function() {
738 | ∙∙var name;
739 | }
740 | ```
741 | - Устанавливайте один пробел перед открывающей скобкой.
742 |
743 | ```javascript
744 | // плохо
745 | function test(){
746 | console.log('test');
747 | }
748 |
749 | // хорошо
750 | function test() {
751 | console.log('test');
752 | }
753 |
754 | // плохо
755 | dog.set('attr',{
756 | age: '1 year',
757 | breed: 'Bernese Mountain Dog'
758 | });
759 |
760 | // хорошо
761 | dog.set('attr', {
762 | age: '1 year',
763 | breed: 'Bernese Mountain Dog'
764 | });
765 | ```
766 | - Оставляйте новую строку в конце файла.
767 |
768 | ```javascript
769 | // плохо
770 | (function(global) {
771 | // ...код...
772 | })(this);
773 | ```
774 |
775 | ```javascript
776 | // хорошо
777 | (function(global) {
778 | // ...код...
779 | })(this);
780 |
781 | ```
782 |
783 | - Используйте отступы, когда делаете цепочки вызовов.
784 |
785 | ```javascript
786 | // плохо
787 | $('#items').find('.selected').highlight().end().find('.open').updateCount();
788 |
789 | // хорошо
790 | $('#items')
791 | .find('.selected')
792 | .highlight()
793 | .end()
794 | .find('.open')
795 | .updateCount();
796 |
797 | // плохо
798 | var leds = stage.selectAll('.led').data(data).enter().append('svg:svg').class('led', true)
799 | .attr('width', (radius + margin) * 2).append('svg:g')
800 | .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
801 | .call(tron.led);
802 |
803 | // хорошо
804 | var leds = stage.selectAll('.led')
805 | .data(data)
806 | .enter().append('svg:svg')
807 | .class('led', true)
808 | .attr('width', (radius + margin) * 2)
809 | .append('svg:g')
810 | .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
811 | .call(tron.led);
812 | ```
813 |
814 | **[[⬆]](#Оглавление)**
815 |
816 | ## Запятые
817 |
818 | - Запятые в начале строки: **Нет.**
819 |
820 | ```javascript
821 | // плохо
822 | var once
823 | , upon
824 | , aTime;
825 |
826 | // хорошо
827 | var once,
828 | upon,
829 | aTime;
830 |
831 | // плохо
832 | var hero = {
833 | firstName: 'Bob'
834 | , lastName: 'Parr'
835 | , heroName: 'Mr. Incredible'
836 | , superPower: 'strength'
837 | };
838 |
839 | // хорошо
840 | var hero = {
841 | firstName: 'Bob',
842 | lastName: 'Parr',
843 | heroName: 'Mr. Incredible',
844 | superPower: 'strength'
845 | };
846 | ```
847 |
848 | - Дополнительная запятая в конце объектов: **Нет**. Она способна вызвать проблемы с IE6/7 и IE9 в режиме совместимости. В некоторых реализациях ES3 запятая в конце массива увеличивает его длину на 1, что может вызвать проблемы. Этот вопрос был прояснен только в ES5 ([оригинал](http://es5.github.io/#D)):
849 |
850 | > Редакция ECMAScript 5 однозначно устанавливает факт, что запятая в конце ArrayInitialiser не должна увеличивать длину массива. Это несемантическое изменение от Редакции ECMAScript 3, но некоторые реализации до этого некорректно разрешали этот вопрос.
851 |
852 | ```javascript
853 | // плохо
854 | var hero = {
855 | firstName: 'Kevin',
856 | lastName: 'Flynn',
857 | };
858 |
859 | var heroes = [
860 | 'Batman',
861 | 'Superman',
862 | ];
863 |
864 | // хорошо
865 | var hero = {
866 | firstName: 'Kevin',
867 | lastName: 'Flynn'
868 | };
869 |
870 | var heroes = [
871 | 'Batman',
872 | 'Superman'
873 | ];
874 | ```
875 |
876 | **[[⬆]](#Оглавление)**
877 |
878 |
879 | ## Точки с запятой
880 |
881 | - **Да.**
882 |
883 | ```javascript
884 | // плохо
885 | (function() {
886 | var name = 'Skywalker'
887 | return name
888 | })()
889 |
890 | // хорошо
891 | (function() {
892 | var name = 'Skywalker';
893 | return name;
894 | })();
895 |
896 | // хорошо
897 | ;(function() {
898 | var name = 'Skywalker';
899 | return name;
900 | })();
901 | ```
902 |
903 | **[[⬆]](#Оглавление)**
904 |
905 |
906 | ## Приведение типов
907 |
908 | - Выполняйте приведение типов в начале операции, но не делайте его избыточным.
909 | - Строки:
910 |
911 | ```javascript
912 | // => this.reviewScore = 9;
913 |
914 | // плохо
915 | var totalScore = this.reviewScore + '';
916 |
917 | // хорошо
918 | var totalScore = '' + this.reviewScore;
919 |
920 | // плохо
921 | var totalScore = '' + this.reviewScore + ' итого';
922 |
923 | // хорошо
924 | var totalScore = this.reviewScore + ' итого';
925 | ```
926 |
927 | - Используйте `parseInt` для чисел и всегда указывайте основание для приведения типов.
928 |
929 | ```javascript
930 | var inputValue = '4';
931 |
932 | // плохо
933 | var val = new Number(inputValue);
934 |
935 | // плохо
936 | var val = +inputValue;
937 |
938 | // плохо
939 | var val = inputValue >> 0;
940 |
941 | // плохо
942 | var val = parseInt(inputValue);
943 |
944 | // хорошо
945 | var val = Number(inputValue);
946 |
947 | // хорошо
948 | var val = parseInt(inputValue, 10);
949 | ```
950 |
951 | - Если по какой-либо причине вы делаете что-то дикое, и именно на `parseInt` тратится больше всего ресурсов, используйте побитовый сдвиг [из соображений быстродействия](http://jsperf.com/coercion-vs-casting/3), но обязательно оставьте комментарий с объяснением причин.
952 |
953 | ```javascript
954 | // хорошо
955 | /**
956 | * этот код медленно работал из-за parseInt
957 | * побитовый сдвиг строки для приведения ее к числу
958 | * работает значительно быстрее.
959 | */
960 | var val = inputValue >> 0;
961 | ```
962 |
963 | - **Примечание:** Будьте осторожны с побитовыми операциями. Числа в JavaScript являются [64-битными значениями](http://es5.github.io/#x4.3.19), но побитовые операции всегда возвращают 32-битные значенения. [Источник](http://es5.github.io/#x11.7). Побитовые операции над числами, значение которых выходит за 32 бита (верхний предел: 2,147,483,647).
964 |
965 | ```
966 | 2147483647 >> 0 //=> 2147483647
967 | 2147483648 >> 0 //=> -2147483648
968 | 2147483649 >> 0 //=> -2147483647
969 | ```
970 |
971 | - логические типы(Boolean):
972 |
973 | ```javascript
974 | var age = 0;
975 |
976 | // плохо
977 | var hasAge = new Boolean(age);
978 |
979 | // хорошо
980 | var hasAge = Boolean(age);
981 |
982 | // хорошо
983 | var hasAge = !!age;
984 | ```
985 |
986 | **[[⬆]](#Оглавление)**
987 |
988 |
989 | ## Соглашение об именовании
990 |
991 | - Избегайте однобуквенных имен функций. Имена должны давать представление о том, что делает эта функция.
992 |
993 | ```javascript
994 | // плохо
995 | function q() {
996 | // ...код...
997 | }
998 |
999 | // хорошо
1000 | function query() {
1001 | // ...код...
1002 | }
1003 | ```
1004 |
1005 | - Используйте camelCase для именования объектов, функций и переменных.
1006 |
1007 | ```javascript
1008 | // плохо
1009 | var OBJEcttsssss = {};
1010 | var this_is_my_object = {};
1011 | function c() {};
1012 | var u = new user({
1013 | name: 'Bob Parr'
1014 | });
1015 |
1016 | // хорошо
1017 | var thisIsMyObject = {};
1018 | function thisIsMyFunction() {};
1019 | var user = new User({
1020 | name: 'Bob Parr'
1021 | });
1022 | ```
1023 |
1024 | - Используйте PascalCase для именования конструкторов классов
1025 |
1026 | ```javascript
1027 | // плохо
1028 | function user(options) {
1029 | this.name = options.name;
1030 | }
1031 |
1032 | var bad = new user({
1033 | name: 'Плохиш'
1034 | });
1035 |
1036 | // хорошо
1037 | function User(options) {
1038 | this.name = options.name;
1039 | }
1040 |
1041 | var good = new User({
1042 | name: 'Кибальчиш'
1043 | });
1044 | ```
1045 |
1046 | - Используйте подчеркивание `_` в качестве префикса для именования внутренних методов и переменных объекта.
1047 |
1048 | ```javascript
1049 | // плохо
1050 | this.__firstName__ = 'Panda';
1051 | this.firstName_ = 'Panda';
1052 |
1053 | // хорошо
1054 | this._firstName = 'Panda';
1055 | ```
1056 |
1057 | - Создавая ссылку на `this`, используйте `_this`.
1058 |
1059 | ```javascript
1060 | // плохо
1061 | function() {
1062 | var self = this;
1063 | return function() {
1064 | console.log(self);
1065 | };
1066 | }
1067 |
1068 | // плохо
1069 | function() {
1070 | var that = this;
1071 | return function() {
1072 | console.log(that);
1073 | };
1074 | }
1075 |
1076 | // хорошо
1077 | function() {
1078 | var _this = this;
1079 | return function() {
1080 | console.log(_this);
1081 | };
1082 | }
1083 | ```
1084 |
1085 | - Задавайте имена для функций. Это повышает читаемость сообщений об ошибках кода.
1086 |
1087 | ```javascript
1088 | // плохо
1089 | var log = function(msg) {
1090 | console.log(msg);
1091 | };
1092 |
1093 | // хорошо
1094 | var log = function log(msg) {
1095 | console.log(msg);
1096 | };
1097 | ```
1098 |
1099 | **[[⬆]](#Оглавление)**
1100 |
1101 |
1102 | ## Геттеры и сеттеры: функции для доступа к значениям объекта
1103 |
1104 | - Функции универсального доступа к свойствам не требуются
1105 | - Если вам необходимо создать функцию для доступа к переменной, используйте раздельные функции getVal() и setVal('hello')
1106 |
1107 | ```javascript
1108 | // плохо
1109 | dragon.age();
1110 |
1111 | // хорошо
1112 | dragon.getAge();
1113 |
1114 | // плохо
1115 | dragon.age(25);
1116 |
1117 | // хорошо
1118 | dragon.setAge(25);
1119 | ```
1120 |
1121 | - Если свойство является логическим(boolean), используйте isVal() или hasVal()
1122 |
1123 | ```javascript
1124 | // плохо
1125 | if (!dragon.age()) {
1126 | return false;
1127 | }
1128 |
1129 | // хорошо
1130 | if (!dragon.hasAge()) {
1131 | return false;
1132 | }
1133 | ```
1134 |
1135 | - Вы можете создавать функции get() и set(), но будьте логичны и последовательны – то есть не добавляйте свойства, которые не могут быть изменены через эти функции.
1136 |
1137 | ```javascript
1138 | function Jedi(options) {
1139 | options || (options = {});
1140 | var lightsaber = options.lightsaber || 'blue';
1141 | this.set('lightsaber', lightsaber);
1142 | }
1143 |
1144 | Jedi.prototype.set = function(key, val) {
1145 | this[key] = val;
1146 | };
1147 |
1148 | Jedi.prototype.get = function(key) {
1149 | return this[key];
1150 | };
1151 | ```
1152 |
1153 | **[[⬆]](#Оглавление)**
1154 |
1155 |
1156 | ## Конструкторы
1157 |
1158 | - Присваивайте метод прототипу вместо замены прототипа на другой объект. Замена прототипа на другой объект делает наследование невозможным.
1159 |
1160 | ```javascript
1161 | function Jedi() {
1162 | console.log('new jedi');
1163 | }
1164 |
1165 | // плохо
1166 | Jedi.prototype = {
1167 | fight: function fight() {
1168 | console.log('fighting');
1169 | },
1170 |
1171 | block: function block() {
1172 | console.log('blocking');
1173 | }
1174 | };
1175 |
1176 | // хорошо
1177 | Jedi.prototype.fight = function fight() {
1178 | console.log('fighting');
1179 | };
1180 |
1181 | Jedi.prototype.block = function block() {
1182 | console.log('blocking');
1183 | };
1184 | ```
1185 |
1186 | - Методы могут возвращать `this` для создания цепочек вызовов. Но стоит оставаться последовательным и обеспечить одинаковое поведение для всех методов, кроме геттеров.
1187 |
1188 | ```javascript
1189 | // плохо
1190 | Jedi.prototype.jump = function() {
1191 | this.jumping = true;
1192 | return true;
1193 | };
1194 |
1195 | Jedi.prototype.setHeight = function(height) {
1196 | this.height = height;
1197 | };
1198 |
1199 | var luke = new Jedi();
1200 | luke.jump(); // => true
1201 | luke.setHeight(20) // => undefined
1202 |
1203 | // хорошо
1204 | Jedi.prototype.jump = function() {
1205 | this.jumping = true;
1206 | return this;
1207 | };
1208 |
1209 | Jedi.prototype.setHeight = function(height) {
1210 | this.height = height;
1211 | return this;
1212 | };
1213 |
1214 | var luke = new Jedi();
1215 |
1216 | luke.jump()
1217 | .setHeight(20);
1218 | ```
1219 |
1220 |
1221 | - Вы можете заменить стандартный метод toString(), но убедитесь, что он работает и не вызывает побочных эффектов.
1222 |
1223 | ```javascript
1224 | function Jedi(options) {
1225 | options || (options = {});
1226 | this.name = options.name || 'no name';
1227 | }
1228 |
1229 | Jedi.prototype.getName = function getName() {
1230 | return this.name;
1231 | };
1232 |
1233 | Jedi.prototype.toString = function toString() {
1234 | return 'Jedi - ' + this.getName();
1235 | };
1236 | ```
1237 |
1238 | **[[⬆]](#Оглавление)**
1239 |
1240 |
1241 | ## События
1242 |
1243 | - Подключая набор данных к событиям (как DOM-событиям, так и js-событиям, например, в Backbone), передавайте объект вместо простой переменной. Это позволяет в процессе всплытия событий добавлять к данному объекту дополнительную информацию.
1244 |
1245 | ```js
1246 | // плохо
1247 | $(this).trigger('listingUpdated', listing.id);
1248 |
1249 | ...
1250 |
1251 | $(this).on('listingUpdated', function(e, listing) {
1252 | //делаем что-нибудь с listing, например:
1253 | listing.name = listings[listing.id]
1254 | });
1255 | ```
1256 |
1257 | prefer:
1258 |
1259 | ```js
1260 | // хорошо
1261 | $(this).trigger('listingUpdated', { listingId : listing.id });
1262 |
1263 | ...
1264 |
1265 | $(this).on('listingUpdated', function(e, data) {
1266 | // делаем что-нибудь с data.listingId
1267 | });
1268 | ```
1269 |
1270 | **[[⬆]](#Оглавление)**
1271 |
1272 |
1273 | ## Модули
1274 |
1275 | - Модуль должен начинаться с `!`. За счет этого даже некорректно сформированный модуль, в конце которого отсутствует точка с запятой, не вызовет ошибок при автоматической сборке скриптов. [Объяснение](https://github.com/airbnb/javascript/issues/44#issuecomment-13063933)
1276 | - Файл должен быть именован с camelCase, находиться в папке с тем же именем, и совпадать с именем экспортируемой переменной.
1277 | - Добавьте метод noConflict(), устанавливающий экспортируемый модуль в состояние предыдущей версии.
1278 | - Всегда объявляйте `'use strict';` в начале модуля.
1279 |
1280 | ```javascript
1281 | // fancyInput/fancyInput.js
1282 |
1283 | !function(global) {
1284 | 'use strict';
1285 |
1286 | var previousFancyInput = global.FancyInput;
1287 |
1288 | function FancyInput(options) {
1289 | this.options = options || {};
1290 | }
1291 |
1292 | FancyInput.noConflict = function noConflict() {
1293 | global.FancyInput = previousFancyInput;
1294 | return FancyInput;
1295 | };
1296 |
1297 | global.FancyInput = FancyInput;
1298 | }(this);
1299 | ```
1300 |
1301 | **[[⬆]](#Оглавление)**
1302 |
1303 |
1304 | ## jQuery
1305 |
1306 | - Для jQuery-переменных используйте префикс `$`.
1307 |
1308 | ```javascript
1309 | // плохо
1310 | var sidebar = $('.sidebar');
1311 |
1312 | // хорошо
1313 | var $sidebar = $('.sidebar');
1314 | ```
1315 |
1316 | - Кэшируйте jQuery-запросы. Каждый новый jQuery-запрос делает повторный поиск по DOM-дереву, и приложение начинает работать медленнее.
1317 |
1318 | ```javascript
1319 | // плохо
1320 | function setSidebar() {
1321 | $('.sidebar').hide();
1322 |
1323 | // ...код...
1324 |
1325 | $('.sidebar').css({
1326 | 'background-color': 'pink'
1327 | });
1328 | }
1329 |
1330 | // хорошо
1331 | function setSidebar() {
1332 | var $sidebar = $('.sidebar');
1333 | $sidebar.hide();
1334 |
1335 | // ...код...
1336 |
1337 | $sidebar.css({
1338 | 'background-color': 'pink'
1339 | });
1340 | }
1341 | ```
1342 |
1343 | - Для DOM-запросов используйте классический каскадный CSS-синтаксис `$('.sidebar ul')` или родитель > потомок `$('.sidebar > ul')`. [jsPerf](http://jsperf.com/jquery-find-vs-context-sel/16)
1344 | - Используйте `find` для поиска внутри DOM-объекта.
1345 |
1346 | ```javascript
1347 | // плохо
1348 | $('ul', '.sidebar').hide();
1349 |
1350 | // плохо
1351 | $('.sidebar').find('ul').hide();
1352 |
1353 | // хорошо
1354 | $('.sidebar ul').hide();
1355 |
1356 | // хорошо
1357 | $('.sidebar > ul').hide();
1358 |
1359 | // хорошо
1360 | $sidebar.find('ul');
1361 | ```
1362 |
1363 | **[[⬆]](#Оглавление)**
1364 |
1365 |
1366 | ## Совместимость ECMAScript 5
1367 |
1368 | - Опирайтесь на [таблицу совместимости](http://kangax.github.com/es5-compat-table/) с ES5 от [Kangax](https://twitter.com/kangax/)
1369 |
1370 | **[[⬆]](#Оглавление)**
1371 |
1372 |
1373 | ## Тестирование
1374 |
1375 | - **Да.**
1376 |
1377 | ```javascript
1378 | function() {
1379 | return true;
1380 | }
1381 | ```
1382 |
1383 | **[[⬆]](#Оглавление)**
1384 |
1385 |
1386 | ## Быстродействие
1387 |
1388 | - [On Layout & Web Performance](http://kellegous.com/j/2013/01/26/layout-performance/)
1389 | - [String vs Array Concat](http://jsperf.com/string-vs-array-concat/2)
1390 | - [Try/Catch Cost In a Loop](http://jsperf.com/try-catch-in-loop-cost)
1391 | - [Bang Function](http://jsperf.com/bang-function)
1392 | - [jQuery Find vs Context, Selector](http://jsperf.com/jquery-find-vs-context-sel/13)
1393 | - [innerHTML vs textContent for script text](http://jsperf.com/innerhtml-vs-textcontent-for-script-text)
1394 | - [Long String Concatenation](http://jsperf.com/ya-string-concat)
1395 | - В процессе наполнения...
1396 |
1397 | **[[⬆]](#Оглавление)**
1398 |
1399 |
1400 | ## Ресурсы
1401 |
1402 |
1403 | **Прочитайте это**
1404 |
1405 | - [Annotated ECMAScript 5.1](http://es5.github.com/)
1406 |
1407 | **Другие руководства по стилю**
1408 |
1409 | - [Google JavaScript Style Guide](http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml)
1410 | - [jQuery Core Style Guidelines](http://docs.jquery.com/JQuery_Core_Style_Guidelines)
1411 | - [Principles of Writing Consistent, Idiomatic JavaScript](https://github.com/rwldrn/idiomatic.js/)
1412 |
1413 | **Другие стили**
1414 |
1415 | - [Naming this in nested functions](https://gist.github.com/4135065) - Christian Johansen
1416 | - [Conditional Callbacks](https://github.com/airbnb/javascript/issues/52)
1417 | - [Popular JavaScript Coding Conventions on Github](http://sideeffect.kr/popularconvention/#javascript)
1418 |
1419 | **Дальнейшее прочтение**
1420 |
1421 | - [Understanding JavaScript Closures](http://javascriptweblog.wordpress.com/2010/10/25/understanding-javascript-closures/) - Angus Croll
1422 | - [Basic JavaScript for the impatient programmer](http://www.2ality.com/2013/06/basic-javascript.html) - Dr. Axel Rauschmayer
1423 |
1424 | **Книги**
1425 |
1426 | - [JavaScript: The Good Parts](http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742) - Douglas Crockford
1427 | - [JavaScript Patterns](http://www.amazon.com/JavaScript-Patterns-Stoyan-Stefanov/dp/0596806752) - Stoyan Stefanov
1428 | - [Pro JavaScript Design Patterns](http://www.amazon.com/JavaScript-Design-Patterns-Recipes-Problem-Solution/dp/159059908X) - Ross Harmes and Dustin Diaz
1429 | - [High Performance Web Sites: Essential Knowledge for Front-End Engineers](http://www.amazon.com/High-Performance-Web-Sites-Essential/dp/0596529309) - Steve Souders
1430 | - [Maintainable JavaScript](http://www.amazon.com/Maintainable-JavaScript-Nicholas-C-Zakas/dp/1449327680) - Nicholas C. Zakas
1431 | - [JavaScript Web Applications](http://www.amazon.com/JavaScript-Web-Applications-Alex-MacCaw/dp/144930351X) - Alex MacCaw
1432 | - [Pro JavaScript Techniques](http://www.amazon.com/Pro-JavaScript-Techniques-John-Resig/dp/1590597273) - John Resig
1433 | - [Smashing Node.js: JavaScript Everywhere](http://www.amazon.com/Smashing-Node-js-JavaScript-Everywhere-Magazine/dp/1119962595) - Guillermo Rauch
1434 | - [Secrets of the JavaScript Ninja](http://www.amazon.com/Secrets-JavaScript-Ninja-John-Resig/dp/193398869X) - John Resig and Bear Bibeault
1435 | - [Human JavaScript](http://humanjavascript.com/) - Henrik Joreteg
1436 | - [Superhero.js](http://superherojs.com/) - Kim Joar Bekkelund, Mads Mobæk, & Olav Bjorkoy
1437 | - [JSBooks](http://jsbooks.revolunet.com/)
1438 |
1439 | **Блоги**
1440 |
1441 | - [DailyJS](http://dailyjs.com/)
1442 | - [JavaScript Weekly](http://javascriptweekly.com/)
1443 | - [JavaScript, JavaScript...](http://javascriptweblog.wordpress.com/)
1444 | - [Bocoup Weblog](http://weblog.bocoup.com/)
1445 | - [Adequately Good](http://www.adequatelygood.com/)
1446 | - [NCZOnline](http://www.nczonline.net/)
1447 | - [Perfection Kills](http://perfectionkills.com/)
1448 | - [Ben Alman](http://benalman.com/)
1449 | - [Dmitry Baranovskiy](http://dmitry.baranovskiy.com/)
1450 | - [Dustin Diaz](http://dustindiaz.com/)
1451 | - [nettuts](http://net.tutsplus.com/?s=javascript)
1452 |
1453 | **[[⬆]](#Оглавление)**
1454 |
1455 | ## В реальном мире
1456 |
1457 | Вот неполный список организаций, которые опираются на оригинальное руководство от AirBnB. Если вы собираетесь использовать это переведенное руководство, сделайте pull request, и мы сможем начать отдельный список компаний, использующих данный перевод.
1458 |
1459 | - **Aan Zee**: [AanZee/javascript](https://github.com/AanZee/javascript)
1460 | - **Airbnb**: [airbnb/javascript](https://github.com/airbnb/javascript)
1461 | - **American Insitutes for Research**: [AIRAST/javascript](https://github.com/AIRAST/javascript)
1462 | - **Compass Learning**: [compasslearning/javascript-style-guide](https://github.com/compasslearning/javascript-style-guide)
1463 | - **ExactTarget**: [ExactTarget/javascript](https://github.com/ExactTarget/javascript)
1464 | - **Gawker Media**: [gawkermedia/javascript](https://github.com/gawkermedia/javascript)
1465 | - **GeneralElectric**: [GeneralElectric/javascript](https://github.com/GeneralElectric/javascript)
1466 | - **GoodData**: [gooddata/gdc-js-style](https://github.com/gooddata/gdc-js-style)
1467 | - **Grooveshark**: [grooveshark/javascript](https://github.com/grooveshark/javascript)
1468 | - **How About We**: [howaboutwe/javascript](https://github.com/howaboutwe/javascript)
1469 | - **Mighty Spring**: [mightyspring/javascript](https://github.com/mightyspring/javascript)
1470 | - **MinnPost**: [MinnPost/javascript](https://github.com/MinnPost/javascript)
1471 | - **ModCloth**: [modcloth/javascript](https://github.com/modcloth/javascript)
1472 | - **National Geographic**: [natgeo/javascript](https://github.com/natgeo/javascript)
1473 | - **National Park Service**: [nationalparkservice/javascript](https://github.com/nationalparkservice/javascript)
1474 | - **Razorfish**: [razorfish/javascript-style-guide](https://github.com/razorfish/javascript-style-guide)
1475 | - **Shutterfly**: [shutterfly/javascript](https://github.com/shutterfly/javascript)
1476 | - **Userify**: [userify/javascript](https://github.com/userify/javascript)
1477 | - **Zillow**: [zillow/javascript](https://github.com/zillow/javascript)
1478 | - **ZocDoc**: [ZocDoc/javascript](https://github.com/ZocDoc/javascript)
1479 |
1480 | ## Переводы
1481 |
1482 | Это руководство так же переведено на:
1483 |
1484 | - :de: **Немецкий**: [timofurrer/javascript-style-guide](https://github.com/timofurrer/javascript-style-guide)
1485 | - :jp: **Японский**: [mitsuruog/javacript-style-guide](https://github.com/mitsuruog/javacript-style-guide)
1486 | - :br: **Португальский**: [armoucar/javascript-style-guide](https://github.com/armoucar/javascript-style-guide)
1487 | - :cn: **Китайский**: [adamlu/javascript-style-guide](https://github.com/adamlu/javascript-style-guide)
1488 | - :es: **Испанский**: [paolocarrasco/javascript-style-guide](https://github.com/paolocarrasco/javascript-style-guide)
1489 | - :kr: **Корейский**: [tipjs/javascript-style-guide](https://github.com/tipjs/javascript-style-guide)
1490 |
1491 | ## Лицензия
1492 |
1493 | (The MIT License)
1494 |
1495 | Copyright (c) 2012 Airbnb: оригинальный текст, (c) 2013 Uprock: перевод
1496 |
1497 | Permission is hereby granted, free of charge, to any person obtaining
1498 | a copy of this software and associated documentation files (the
1499 | 'Software'), to deal in the Software without restriction, including
1500 | without limitation the rights to use, copy, modify, merge, publish,
1501 | distribute, sublicense, and/or sell copies of the Software, and to
1502 | permit persons to whom the Software is furnished to do so, subject to
1503 | the following conditions:
1504 |
1505 | The above copyright notice and this permission notice shall be
1506 | included in all copies or substantial portions of the Software.
1507 |
1508 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
1509 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1510 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1511 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
1512 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
1513 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1514 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1515 |
1516 | **[[⬆]](#Оглавление)**
1517 |
1518 |
--------------------------------------------------------------------------------
/diff.md:
--------------------------------------------------------------------------------
1 | Отличия от оригинального руководства от AirBnB:
2 | -в разделе "комментарии" предлагается использовать аннотирование задач через `FIXME` и `TODO`. `FIXME` был убран, так как многие IDE (например, IntelliJ) автоматически обнаруживают и работают только с комментариями `TODO`. Вместо этого предлагается синтаксис `TODO FIXME`
--------------------------------------------------------------------------------
/linters/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "esnext": true,
3 |
4 | "node": true,
5 |
6 | "browser": true,
7 |
8 | "jquery": true,
9 |
10 | "camelcase": true,
11 |
12 | "eqeqeq": true,
13 |
14 | "eqnull": true,
15 |
16 | "indent": 2,
17 |
18 | "latedef": true,
19 |
20 | "newcap": true,
21 |
22 | "quotmark": "single",
23 |
24 | "trailing": true,
25 |
26 | "undef": true,
27 |
28 | "unused": true
29 | }
--------------------------------------------------------------------------------
/linters/SublimeLinter/SublimeLinter.sublime-settings:
--------------------------------------------------------------------------------
1 | /**
2 | * Airbnb JSHint settings for use with SublimeLinter and Sublime Text 2.
3 | *
4 | * 1. Install SublimeLinter at https://github.com/SublimeLinter/SublimeLinter
5 | * 2. Open user preferences for the SublimeLinter package in Sublime Text 2
6 | * * For Mac OS X go to _Sublime Text 2_ > _Preferences_ > _Package Settings_ > _SublimeLinter_ > _Settings - User_
7 | * 3. Paste the contents of this file into your settings file
8 | * 4. Save the settings file
9 | *
10 | * @version 0.3.0
11 | * @see https://github.com/SublimeLinter/SublimeLinter
12 | * @see http://www.jshint.com/docs/
13 | */
14 | {
15 | "jshint_options":
16 | {
17 | /*
18 | * ENVIRONMENTS
19 | * =================
20 | */
21 |
22 | // Define globals exposed by modern browsers.
23 | "browser": true,
24 |
25 | // Define globals exposed by jQuery.
26 | "jquery": true,
27 |
28 | // Define globals exposed by Node.js.
29 | "node": true,
30 |
31 | /*
32 | * ENFORCING OPTIONS
33 | * =================
34 | */
35 |
36 | // Force all variable names to use either camelCase style or UPPER_CASE
37 | // with underscores.
38 | "camelcase": true,
39 |
40 | // Prohibit use of == and != in favor of === and !==.
41 | "eqeqeq": true,
42 |
43 | // Suppress warnings about == null comparisons.
44 | "eqnull": true,
45 |
46 | // Enforce tab width of 2 spaces.
47 | "indent": 2,
48 |
49 | // Prohibit use of a variable before it is defined.
50 | "latedef": true,
51 |
52 | // Require capitalized names for constructor functions.
53 | "newcap": true,
54 |
55 | // Enforce use of single quotation marks for strings.
56 | "quotmark": "single",
57 |
58 | // Prohibit trailing whitespace.
59 | "trailing": true,
60 |
61 | // Prohibit use of explicitly undeclared variables.
62 | "undef": true,
63 |
64 | // Warn when variables are defined but never used.
65 | "unused": true
66 | }
67 | }
68 |
--------------------------------------------------------------------------------