├── .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 = ''; 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 | --------------------------------------------------------------------------------