JavaScript Style Guide - Lebedancer/component-example GitHub Wiki

  1. Типы
  2. Объекты
  3. Массивы
  4. Строки
  5. Функции
  6. Свойства
  7. Переменные
  8. Область видимости и "поднятие"
  9. Условные выражения и равенства
  10. Блоки кода
  11. Комментарии
  12. Пробелы
  13. Запятые
  14. Точки с запятой
  15. Приведение типов
  16. Соглашения об именовании
  17. Функции доступа get и set
  18. Конструкторы
  19. События
  20. Модули
  21. jQuery

Изменение прототипов встроенных объектов - НЕТ

Изменение встроенных объектов, таких как Object.prototype и Array.prototype, запрещено. Изменение других втроенных объектов, так как Function.prototype, менее опасно, но все же приводят с сложностям при разработке, и его следует избегать.

  • Простые типы: Когда вы взаимодействуете с простым типом, вы работаете непосредственно с его значением

    • string
    • number
    • boolean
    • null
    • undefined
    var foo = 1;
    var bar = foo;
    
    bar = 9;
    
    console.log(foo, bar); // => 1, 9
  • Сложные типы: Когда вы взаимодействуете со сложным типом, вы работаете со ссылкой на его значение.

    • object
    • array
    • function
    var foo = [1, 2];
    var bar = foo;
    
    bar[0] = 9;
    
    console.log(foo[0], bar[0]); // => 9, 9

  • Для создания объекта используйте фигурные скобки

    // плохо
    var item = new Object();
    
    // хорошо
    var item = {};
  • Не используйте зарезервированные слова в качестве ключей объекта. Это не будет работать в IE8. Подробнее

    // плохо
    var superman = {
      default: { clark: 'kent' },
      private: true
    };
    
    // хорошо
    var superman = {
      defaults: { clark: 'kent' },
      hidden: true
    };
  • Используйте синонимы вместо зарезервированных слов

    // плохо
    var superman = {
      class: 'alien'
    };
    
    // плохо
    var superman = {
      klass: 'alien'
    };
    
    // хорошо
    var superman = {
      type: 'alien'
    };
  • Не используйте лишние кавычки

    // плохо
    var superman = {
      'attr': 'alien'
    };
    
    // хорошо
    var superman = {
      attr: 'alien'
    };
    
    // хорошо
    var superman = {
      'data-type': 'alien'
    };

  • Используйте квадратные скобки для создания массива

    // плохо
    var items = new Array();
    
    // хорошо
    var items = [];
  • Если длина массива неизвестна, используйте Array#push.

    var someStack = [];
    
    
    // плохо
    someStack[someStack.length] = 'abracadabra';
    
    // хорошо
    someStack.push('abracadabra');
  • Если необходимо скопировать массив, используйте Array#slice. jsPerf

    var len = items.length;
    var itemsCopy = [];
    var i;
    
    // плохо
    for (i = 0; i < len; i++) {
      itemsCopy[i] = items[i];
    }
    
    // хорошо
    itemsCopy = items.slice();
  • Чтобы создать из похожего на массив объекта массив, используйте Array#slice.

    function trigger() {
      var args = Array.prototype.slice.call(arguments);
      ...
    }

  • Используйте одинарные кавычки '' для строк

    // плохо
    var name = "Bob Parr";
    
    // хорошо
    var name = 'Bob Parr';
    
    // плохо
    var fullName = "Bob " + this.lastName;
    
    // хорошо
    var fullName = 'Bob ' + this.lastName;
  • Строки длиннее 80 символов нужно разделять, выполняя перенос через конкатенацию строк.

  • Примечание: строки с большим количеством конкатенаций могут отрицательно влиять на быстродействие. jsPerf и обсуждение

    // плохо
    var errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.';
    
    // плохо
    var errorMessage = 'This is a super long error that \
    was thrown because of Batman. \
    When you stop to think about \
    how Batman had anything to do \
    with this, you would get nowhere \
    fast.';
    
    
    // хорошо
    var errorMessage = 'This is a super long error that ' +
      'was thrown because of Batman. ' +
      'When you stop to think about ' +
      'how Batman had anything to do ' +
      'with this, you would get nowhere ' +
      'fast.';
  • Когда строка создается программным путем, используйте Array#join вместо объединения строк. В основном для IE:jsPerf.

    var items;
    var messages;
    var length;
    var i;
    
    messages = [{
      state: 'success',
      message: 'This one worked.'
    }, {
      state: 'success',
      message: 'This one worked as well.'
    }, {
      state: 'error',
      message: 'This one did not work.'
    }];
    
    length = messages.length;
    
    // плохо
    function inbox(messages) {
      items = '<ul>';
    
      for (i = 0; i < length; i++) {
        items += '<li>' + messages[i].message + '</li>';
      }
    
      return items + '</ul>';
    }
    
    // хорошо
    function inbox(messages) {
      items = [];
    
      for (i = 0; i < length; i++) {
        items[i] = messages[i].message;
      }
    
      return '<ul><li>' + items.join('</li><li>') + '</li></ul>';
    }

  • Объявление функций:

    // объявление анонимной функции
    var anonymous = function() {
      return true;
    };
    
    // объявление именованной функции
    var named = function named() {
      return true;
    };
    
    // объявление функции, которая сразу же выполняется (IIFE)
    (function() {
      console.log('Welcome to the Internet. Please follow me.');
    })();
  • Старайтесь иметь только 1 точку выхода из функции:

 
 // плохо
 function() {
   if(true) {
       return true;
   } else if(true) {
       return false;
   } else {
       return true;
   }
 };

  // хорошо
 function() {
   var result;

   if(true) {
       result = true;
   } else if(true) {
       result = false;
   } else {
       result = true;
   }

   return result;
 };
 ```
- Допускается иметь несколько точек выхода:
 1. Return в начале метода, для моментального выхода из функции.
 1. Пара return стоит близко друг к другу.

- Никогда не объявляйте функцию внутри блока кода - не функции (if, while, else и т.д.). Вместо этого присваивайте функцию уже объявленной через var переменной. Это будет работать, но в различных браузерах по-разному.
- **Примечание :** ECMA-262 устанавливает понятие блока как списка операторов. Объявление функции не является оператором. [Комментарий по этому вопросу в ECMA-262](http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf#page=97).

 ```javascript
 // плохо
 if (currentUser) {
   function test() {
     console.log('Nope.');
   }
 }

 // хорошо
 var test;
 if (currentUser) {
   test = function test() {
     console.log('Yup.');
   };
 }
 ```

- Никогда не называйте параметр функции `arguments`, он будет более приоритетным над объектом arguments, который доступен для каждой функции.

 ```javascript
 // плохо
 function nope(name, options, arguments) {
   // ...код...
 }

 // хорошо
 function yup(name, options, args) {
   // ...код...
 }
 ```

 **[⬆](#TOC)**

## <a name='properties'>Свойства</a>

- Используйте точечную нотацию для доступа к свойствам и методам.

 ```javascript
 var luke = {
   jedi: true,
   age: 28
 };

 // плохо
 var isJedi = luke['jedi'];

 // хорошо
 var isJedi = luke.jedi;
 ```

- Используйте квадратные скобки для доступа к свойству, имя которого хранится в переменной.

 ```javascript
 var luke = {
   jedi: true,
   age: 28
 };

 function getProp(prop) {
   return luke[prop];
 }

 var isJedi = getProp('jedi');
 ```

 **[⬆](#TOC)**

## <a name='variables'>Переменные</a>

- Всегда используйте `var` для объявления переменных. В противном случае переменная будет объявлена глобальной. Необходимо избегать загрязнения глобального пространства имен.

 ```javascript
 // плохо
 superPower = new SuperPower();

 // хорошо
 var superPower = new SuperPower();
 ```

- Используйте `var` для каждой переменной и объявляйте каждую переменную на новой строке.

 ```javascript
 // плохо
 var items = getItems(),
     goSportsTeam = true,
     dragonball = 'z';

 // хорошо
 var items = getItems();
 var goSportsTeam = true;
 var dragonball = 'z';


 ```

- Объявляйте переменные, которым не присваивается значение, последними. Это удобно, когда вам необходимо будет задать значение одной из этих переменных в зависимости от уже присвоенных значений предыдущих переменных.

 ```javascript
 // плохо
 var i;
 var len;
 var dragonball;
 var items = getItems();
 var goSportsTeam = true;

 // плохо
 var i;
 var items = getItems();
 var dragonball;
 var goSportsTeam = true;
 var len;

 // хорошо
 var items = getItems();
 var goSportsTeam = true;
 var dragonball;
 var len;
 var i;
 ```

- Присваивайте переменные в начале области видимости. Это помогает избегать проблем с объявлением переменных и областями видимости.

 ```javascript
 // плохо
 function() {
   test();
   console.log('делаю что-то..');

   //..делаю что-то еще..

   var name = getName();

   if (name === 'test') {
     return false;
   }

   return name;
 }

 // хорошо
 function() {
   var name = getName();

   test();
   console.log('делаю что-то..');

   //..делаю что-то еще..

   if (name === 'test') {
     return false;
   }

   return name;
 }

 // плохо
 function() {
   var name = getName();

   if (!arguments.length) {
     return false;
   }

   return true;
 }

 // хорошо
 function() {
   if (!arguments.length) {
     return false;
   }

   var name = getName();

   return true;
 }
 ```

 **[⬆](#TOC)**

## <a name='hoisting'>Область видимости и "поднятие"</a>

- Объявление переменных "поднимается" в начало области видимости, а присвоение — нет.

 ```javascript
 // Мы знаем, что это не будет работать
 // если нет глобальной переменной notDefined
 function example() {
   console.log(notDefined); // => throws a ReferenceError
 }

 // Объявление переменной после попытки ее использования
 // будет работать по правилу "поднятия"
 // Заметьте, что присвоение значения `true` не поднимается
 function example() {
   console.log(declaredButNotAssigned); // => undefined
   var declaredButNotAssigned = true;
 }

 // Интерпретатор переносит объявление переменной
 // к началу области видимости.
 // Что значит, что предыдущий пример будет воспринят так:
 function example() {
   var declaredButNotAssigned;
   console.log(declaredButNotAssigned); // => undefined
   declaredButNotAssigned = true;
 }
 ```

- Объявление анонимной функции поднимает наверх области видимости переменную, но не ее значение.

 ```javascript
 function example() {
   console.log(anonymous); // => undefined

   anonymous(); // => TypeError anonymous is not a function

   var anonymous = function() {
     console.log('anonymous function expression');
   };
 }
 ```

- Объявление именованной функции поднимает переменную, не ее имя функции или ее тело.
 ```javascript
 function example() {
   console.log(named); // => undefined

   named(); // => TypeError named is not a function

   superPower(); // => ReferenceError superPower is not defined

   var named = function superPower() {
     console.log('Flying');
   };
 }

 // То же самое происходит, когда имя функции и имя переменной совпадают.
 function example() {
   console.log(named); // => undefined

   named(); // => TypeError named is not a function

   var named = function named() {
     console.log('named');
   }
 }
 ```

- Объявления функции поднимают и имя, и тело функции.

 ```javascript
 function example() {
   superPower(); // => Flying

   function superPower() {
     console.log('Flying');
   }
 }
 ```

- Подробнее можно прочитать в статье [JavaScript Scoping & Hoisting](http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting) by [Ben Cherry](http://www.adequatelygood.com/)

 **[⬆](#TOC)**

## <a name='conditionals'>Условные выражения и равенства</a>

- Используйте `===` и`!==` вместо `==` и `!=`.
- Условные выражения вычисляются посредством приведения через метод `ToBoolean` и всегда следуют следующим правилам:

 + **Objects** соответствует **true**
 + **Undefined** соответствует **false**
 + **Null** соответствует **false**
 + **Booleans** остаются неизменными
 + **Numbers** соответствует **false** если имеют значения **+0, -0, или NaN**, иначе **true**
 + **Strings** соответствует **false** если является пустой строкой `''`, иначе **true**

 ```javascript
 if ([0]) {
   // true
   // Массив(Array) является объектом, объекты преобразуются в true
 }
 ```

- Используйте короткий синтаксис.

 ```javascript
 // плохо
 if (name !== '') {
   // ...код...
 }

 // хорошо
 if (name) {
   // ...код...
 }

 // плохо
 if (collection.length > 0) {
   // ...код...
 }

 // хорошо
 if (collection.length) {
   // ...код...
 }
 ```

- Подробнее можно прочитать в статье [Truth Equality and JavaScript](http://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/#more-2108) by Angus Croll

 **[⬆](#TOC)**


## <a name='blocks'>Блоки кода</a>

- Используйте фигурные скобки для всех многострочных блоков.

 ```javascript
 // плохо
 if (test)
   return false;

 // плохо
 if (test) return false;

 // хорошо
 if (test) {
   return false;
 }

 // плохо
 function() { return false; }

 // хорошо
 function() {
   return false;
 }
 ```

 **[⬆](#TOC)**

## <a name='comments'>Комментарии</a>

- Используйте `/** ... */` для многострочных комментариев. Включите описание, опишите типы и значения для всех параметров и возвращаемых значений.

 ```javascript
 // плохо
 // make() возвращает новый элемент
 // основываясь на получаемом имени тэга
 //
 // @param <String> tag
 // @return <Element> element
 function make(tag) {

   // ...код...

   return element;
 }

 // хорошо
 /**
  * make() возвращает новый элемент
  * основываясь на получаемом имени тэга
  *
  * @param <String> tag
  * @return <Element> element
  */
 function make(tag) {

   // ...код...

   return element;
 }
 ```

- Используйте `//` для однострочных комментариев. Размещайте однострочные комментарии на новой строке над темой комментария. Добавляйте пустую строку над комментарием.

 ```javascript
 // плохо
 var active = true;  // is current tab

 // хорошо
 // is current tab
 var active = true;

 // плохо
 function getType() {
   console.log('fetching type...');
   // set the default type to 'no type'
   var type = this._type || 'no type';

   return type;
 }

 // хорошо
 function getType() {
   console.log('fetching type...');

   // set the default type to 'no type'
   var type = this._type || 'no type';

   return type;
 }
 ```

- Префикс `FIXME` или `TODO`  помогает другим разработчикам быстро понять, что вы указываете на проблему, к которой нужно вернуться в дальнейшем, или если вы предлагаете решение проблемы, которое должно быть реализовано. Эти комментарии отличаются от обычных, так как они призывают к действию: `FIXME -- нужно разобраться`, `TODO -- нужно реализовать`.

- Используйте `// FIXME:` чтобы указать на проблему

 ```javascript
 function Calculator() {

   // FIXME: не нужно использовать глобальную переменную
   total = 0;

   return this;
 }
 ```

- Use `// TODO:` для указания решения проблемы

 ```javascript
 function Calculator() {

   // TODO: должна быть возможность изменять значение через параметр функции
   this.total = 0;

   return this;
 }
**[⬆](#TOC)**
  • Используйте табуляцию из 4 пробелов

    // плохо
    function() {
    ∙∙var name;
    }
    
    // плохо
    function() {
    ∙var name;
    }
    
    // хорошо
    function() {
    ∙∙∙∙var name;
    }
  • Устанавливайте один пробел перед открывающей скобкой.

    // плохо
    function test(){
      console.log('test');
    }
    
    // хорошо
    function test() {
      console.log('test');
    }
    
    // плохо
    dog.set('attr',{
      age: '1 year',
      breed: 'Bernese Mountain Dog'
    });
    
    // хорошо
    dog.set('attr', {
      age: '1 year',
      breed: 'Bernese Mountain Dog'
    });
  • Выделяйте операторы пробелами.

    // плохо
    var x=y+5;
    
    // хорошо
    var x = y + 5;
  • Отделяйте содержимое объекта от скобок пробелами. При написании объекта в строку.

    // плохо
    {name: 'Vasya'}
    
    // хорошо
    { name: 'Vasya' }
  • Используйте отступы, когда делаете цепочки вызовов.

    // плохо
    $('#items').find('.selected').highlight().end().find('.open').updateCount();
    
    // хорошо
    $('#items')
      .find('.selected')
        .highlight()
        .end()
      .find('.open')
        .updateCount();
    
    // плохо
    var leds = stage.selectAll('.led').data(data).enter().append('svg:svg').class('led', true)
        .attr('width',  (radius + margin) * 2).append('svg:g')
        .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
        .call(tron.led);
    
    // хорошо
    var leds = stage.selectAll('.led')
        .data(data)
      .enter().append('svg:svg')
        .class('led', true)
        .attr('width',  (radius + margin) * 2)
      .append('svg:g')
        .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
        .call(tron.led);

  • Запятые в начале строки: Нет.

    // плохо
    var once
      , upon
      , aTime;
    
    // хорошо
    var once,
        upon,
        aTime;
    
    // плохо
    var hero = {
        firstName: 'Bob'
      , lastName: 'Parr'
      , heroName: 'Mr. Incredible'
      , superPower: 'strength'
    };
    
    // хорошо
    var hero = {
      firstName: 'Bob',
      lastName: 'Parr',
      heroName: 'Mr. Incredible',
      superPower: 'strength'
    };
  • Дополнительная запятая в конце объектов: Нет.

    // Плохо
    const hero = {
      firstName: 'Dana',
      lastName: 'Scully',
    };
    
    const heroes = [
      'Batman',
      'Superman',
    ];
    
    // Хорошо
    const hero = {
      firstName: 'Dana',
      lastName: 'Scully'
    };
    
    const heroes = [
      'Batman',
      'Superman'
    ];  

  • Да.

    // плохо
    (function() {
      var name = 'Skywalker'
      return name
    })()
    
    // хорошо
    (function() {
      var name = 'Skywalker';
      return name;
    })();
  • Для плагинов jQuery.

    // хорошо
    ;(function() {
      var name = 'Skywalker';
      return name;
    })();

  • Выполняйте приведение типов в начале операции.

  • Строки:

    //  => this.reviewScore = 9;
    
    // плохо
    var totalScore = this.reviewScore + '';
    
    // хорошо
    var totalScore = '' + this.reviewScore;
    
    // плохо
    var totalScore = '' + this.reviewScore + ' total score';
    
    // хорошо
    var totalScore = this.reviewScore + ' total score';
  • Используйте parseInt для чисел и всегда указывайте основание для приведения типов.

    var inputValue = '4';
    
    // плохо
    var val = new Number(inputValue);
    
    // плохо
    var val = +inputValue;
    
    // плохо
    var val = inputValue >> 0;
    
    // плохо
    var val = parseInt(inputValue);
    
    // хорошо
    var val = Number(inputValue);
    
    // хорошо
    var val = parseInt(inputValue, 10);
  • Если по какой-либо причине на parseInt тратится больше всего ресурсов, используйте побитовый сдвиг из соображений быстродействия, но обязательно оставьте комментарий с объяснением причин.

  • Примечание: Будьте осторожны с побитовыми операциями. Числа в JavaScript являются 64-битными значениями, но побитовые операции всегда возвращают 32-битные значения. (Источник). Побитовые операции над числами, значение которых выходит за 32 бита, могут привести к неожиданному поведению. Обсуждение

    // хорошо
    /**
     * этот код медленно работал из-за parseInt
     * побитовый сдвиг строки для приведения ее к числу
     * работает значительно быстрее.
     */
    var val = inputValue >> 0;
  • Логические типы:

    var age = 0;
    
    // плохо
    var hasAge = new Boolean(age);
    
    // хорошо
    var hasAge = !!age;
    
    // хорошо
    var hasAge = Boolean(age);

  • Избегайте однобуквенных имен. Имена должны давать представление о том, для чего используется переменная/функция.

    // плохо
    function q() {
      // ...код...
    }
    
    // хорошо
    function query() {
      // ..код..
    }
  • Используйте camelCase для именования объектов, функций и переменных.

    // плохо
    var OBJEcttsssss = {};
    var this_is_my_object = {};
    function c() {};
    var u = new user({
      name: 'Bob Parr'
    });
    
    // хорошо
    var thisIsMyObject = {};
    function thisIsMyFunction() {};
    var user = new User({
      name: 'Bob Parr'
    });
  • Используйте camelCase для именования событий

    // плохо
    var $button = $('button');
    $button.trigger('PressMeSoftly');
    
    // плохо
    var $button = $('button');
    $button.trigger('press_Me_Softly');
    
    // хорошо
    var $button = $('button');
    $button.trigger('pressMeSoftly');
  • Используйте PascalCase для именования конструкторов или классов

    // плохо
    function user(options) {
      this.name = options.name;
    }
    
    var bad = new user({
      name: 'nope'
    });
    
    // хорошо
    function User(options) {
      this.name = options.name;
    }
    
    var good = new User({
      name: 'yup'
    });
  • Все приватные свойства должны быть внутри замыкания.

    // плохо
    this.__firstName__ = 'Panda';
    this.firstName_ = 'Panda';
    
    // хорошо
    function animals() {
        var firstName = 'Panda';
        
        return {
            setFirstName: function (firstName) {
                firstName = firstName;
            },
            getFirstName: function() {
                return firstName;
            }
        }
    }
  • Сохраняя ссылку на this, используйте смысл this.

    // плохо
    function() {
      var that = this;
      return function() {
        console.log(that);
      };
    }
    
    // плохо
    function() {
      var _this = this;
      return function() {
        console.log(_this);
      };
    }
    
    // приемлемо
    function() {
      var self = this;
      return function() {
        console.log(self);
      };
    }
    
    // хорошо
    function createPlugin() {
      var createPluginContext = this;
      
      return function() {
        console.log(createPluginContext);
      };
    }
  • Задавайте имена для функций. Это полезно в сообщениях об ошибках(рекомендация).

    // плохо
    var log = function(msg) {
      console.log(msg);
    };
    
    // хорошо
    var log = function log(msg) {
      console.log(msg);
    };

  • Функции универсального доступа к свойствам не требуются

  • Если вам необходимо создать функцию доступа к переменной, используйте getVal() и setVal('hello')

    // плохо
    dragon.age();
    
    // хорошо
    dragon.getAge();
    
    // плохо
    dragon.age(25);
    
    // хорошо
    dragon.setAge(25);
  • Если свойство является логическим(boolean), используйте isVal() или hasVal()

    // плохо
    if (!dragon.age()) {
      return false;
    }
    
    // хорошо
    if (!dragon.hasAge()) {
      return false;
    }
  • Вы можете создавать функции get() и set(), но не добавляйте свойства, которые не могут быть изменены через эти функции.

    function Jedi(options) {
      options || (options = {});
      var lightsaber = options.lightsaber || 'blue';
      this.set('lightsaber', lightsaber);
    }
    
    Jedi.prototype.set = function(key, val) {
      this[key] = val;
    };
    
    Jedi.prototype.get = function(key) {
      return this[key];
    };

  • Присваивайте метод прототипу вместо замены прототипа на другой объект. Замена прототипа на другой объект делает наследование невозможным.

    function Jedi() {
      console.log('new jedi');
    }
    
    // плохо
    Jedi.prototype = {
      fight: function fight() {
        console.log('fighting');
      },
    
      block: function block() {
        console.log('blocking');
      }
    };
    
    // хорошо
    Jedi.prototype.fight = function fight() {
      console.log('fighting');
    };
    
    Jedi.prototype.block = function block() {
      console.log('blocking');
    };
  • Методы могут возвращать this для создания цепочек вызовов.

    // плохо
    Jedi.prototype.jump = function() {
      this.jumping = true;
      return true;
    };
    
    Jedi.prototype.setHeight = function(height) {
      this.height = height;
    };
    
    var luke = new Jedi();
    luke.jump(); // => true
    luke.setHeight(20) // => undefined
    
    // хорошо
    Jedi.prototype.jump = function() {
      this.jumping = true;
      return this;
    };
    
    Jedi.prototype.setHeight = function(height) {
      this.height = height;
      return this;
    };
    
    var luke = new Jedi();
    
    luke.jump()
      .setHeight(20);
  • Вы можете заменить стандартный метод toString(), но убедитесь, что он работает и не вызывает побочных эффектов.

    function Jedi(options) {
      options || (options = {});
      this.name = options.name || 'no name';
    }
    
    Jedi.prototype.getName = function getName() {
      return this.name;
    };
    
    Jedi.prototype.toString = function toString() {
      return 'Jedi - ' + this.getName();
    };

  • Подключая набор данных к событиям (как DOM-событиям, так и более частным, например, в Backbone), передавайте объект вместо простой переменной. Это позволяет впоследствии добавлять больше данных в объект события без переписывания хэндлеров.

    // плохо
    $(this).trigger('listingUpdated', listing.id);
    
    ...
    
    $(this).on('listingUpdated', function(e, listingId) {
      // do something with listingId
    });
    // хорошо
    $(this).trigger('listingUpdated', { listingId : listing.id });
    
    ...
    
    $(this).on('listingUpdated', function(e, data) {
      // do something with data.listingId
    });

  • Модуль должен начинаться с !. За счет этого даже некорректно сформированный модуль, в конце которого отсутствует точка с запятой, не вызовет ошибок при сборке скриптов. Объяснение

  • Файл должен быть именован с camelCase, находиться в папке с тем же именем, и совпадать с именем экспортируемой переменной.

  • Добавьте метод noConflict(), устанавливающий экспортируемый модуль в состояние предыдущей версии и возвращающий его.

  • Всегда объявляйте 'use strict'; в начале модуля.

    // fancyInput/fancyInput.js
    
    !function(global) {
      'use strict';
    
      var previousFancyInput = global.FancyInput;
    
      function FancyInput(options) {
        this.options = options || {};
      }
    
      FancyInput.noConflict = function noConflict() {
        global.FancyInput = previousFancyInput;
        return FancyInput;
      };
    
      global.FancyInput = FancyInput;
    }(this);

  • Для jQuery-переменных используйте префикс $.

    // плохо
    var sidebar = $('.sidebar');
    
    // хорошо
    var $sidebar = $('.sidebar');
  • Кэшируйте jQuery-запросы.

    // плохо
    function setSidebar() {
      $('.sidebar').hide();
    
      // ...код...
    
      $('.sidebar').css({
        'background-color': 'pink'
      });
    }
    
    // хорошо
    function setSidebar() {
      var $sidebar = $('.sidebar');
      $sidebar.hide();
    
      // ...код...
    
      $sidebar.css({
        'background-color': 'pink'
      });
    }
  • Для DOM-запросов используйте каскадный синтаксис $('.sidebar ul') или родитель > потомок $('.sidebar > ul'). jsPerf

  • Используйте find для поиска внутри DOM-объекта.

    // плохо
    $('ul', '.sidebar').hide();
    
    // плохо
    $('.sidebar').find('ul').hide();
    
    // хорошо
    $('.sidebar ul').hide();
    
    // хорошо
    $('.sidebar > ul').hide();
    
    // хорошо
    $sidebar.find('ul').hide();

⚠️ **GitHub.com Fallback** ⚠️