Перевод AirBnB Style Guide — Airbnb JavaScript Style Guide (en) на русский язык от команды Uprock. За что им огромное спасибо! Подробнее о переводе на хабре.
Стиль вашего кода, может сказать о вас достаточно много. Это один из показателей опытного разработчика. Помимо исключительно визуальной составляющей, в переводе содержатся бенчмарки и рекомендации по производительности. А в некоторых случаях, использование такого кодстайла, может избавить вас он проблем связанных с тонкостями языка. Статья является отличным дополнением к вопросам для собеседования кандидату на должность Front-end разработчика и к вашему скилу как разработчика 😉
Оглавление
- Типы
- Объекты
- Массивы
- Строки
- Функции
- Свойства
- Переменные
- Области видимости
- Условные выражения и равенства
- Блоки кода
- Комментарии
- Пробелы
- Запятые
- Точки с запятой
- Приведение типов
- Соглашение об именовании
- Геттеры и сеттеры
- Конструкторы
- События
- Модули
- jQuery
- Совместимость с ES5
- Тестирование
- Быстродействие
- Ресурсы
- В реальном мире
Типы
Простые типы: Когда вы взаимодействуете с простым типом, вы взаимодействуете непосредственно с его значением в памяти.
string
number
boolean
null
undefined
var foo = 1, bar = foo; bar = 9; console.log(foo, bar); // => 1, 9. foo не изменился
Сложные типы: Когда вы взаимодействуете со сложным типом, вы взаимодействуете с ссылкой на его значение в памяти.
object
array
function
var foo = [1, 2], bar = foo; bar[0] = 9; console.log(foo[0], bar[0]); // => 9, 9.
Объекты
Для создания объекта используйте фигурные скобки. Не создавайте объекты через конструктор
new Object
.// плохо 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' };
Массивы
Для создания массива используйте квадратные скобки. Не создавайте массивы через конструктор
new Array
.// плохо var items = new Array(); // хорошо var items = [];
Если вы не знаете длину массива, используйте Array::push.
var someStack = []; // плохо someStack[someStack.length] = 'abracadabra'; // хорошо someStack.push('abracadabra');
Если вам необходимо скопировать массив, используйте Array::slice. jsPerf
var len = items.length, itemsCopy = [], i; // плохо for (i = 0; i < len; i++) { itemsCopy[i] = items[i]; } // хорошо itemsCopy = items.slice();
Чтобы скопировать похожий по свойствам на массив объект (например, NodeList или Arguments), используйте Array::slice.
function trigger() { var args = Array.prototype.slice.call(arguments); ... }
Строки
Используйте одинарные кавычки
''
для строк.// плохо var name = "Боб Дилан"; // хорошо var name = 'Боб Дилан'; // плохо var fullName = "Боб " + this.lastName; // хорошо var fullName = 'Дилан ' + this.lastName;
Строки длиннее 80 символов нужно разделять, выполняя перенос через конкатенацию строк.
Осторожно: строки с большим количеством конкатенаций могут отрицательно влиять на быстродействие. jsPerf и Обсуждение
// плохо var errorMessage = 'Эта сверхдлинная ошибка возникла из-за белой обезъяны. Не говори про обезъяну! Не слушай об обезьяне! Не думай об обезъяне!'; // плохо var errorMessage = 'Эта сверхдлинная ошибка возникла из-за белой обезъяны. \ Не говори про обезъяну! Не слушай об обезьяне! \ Не думай об обезъяне!'; // хорошо var errorMessage = 'Эта сверхдлинная ошибка возникла из-за белой обезъяны. ' + 'Не говори про обезъяну! Не слушай об обезьяне! ' + 'Не думай об обезъяне!';
Когда строка создается программным путем, используйте Array::join вместо объединения строк. В основном для IE: jsPerf.
var items, messages, length, i; messages = [{ state: 'success', message: 'Это работает.' },{ state: 'success', message: 'Это тоже.' },{ state: 'error', message: 'А я томат.' }]; 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; }; // объявление функции, которая сразу же выполняется (замыкание) (function() { console.log('Если вы читаете это, вы открыли консоль.'); })();
- Никогда не объявляйте функцию внутри блока кода — например в if, while, else и так далее. Единственное исключение — блок функции. Вместо этого присваивайте функцию уже объявленной через
var
переменной. Условное объявление функций работает, но в различных браузерах работает по-разному. Примечание ECMA-262 устанавливает понятие
блока
как списка операторов. Объявление функции (не путайте с присвоением функции переменной) не является оператором. Комментарий по этому вопросу в ECMA-262.// плохо if (currentUser) { function test() { console.log('Плохой мальчик.'); } } // хорошо var test; if (currentUser) { test = function test() { console.log('Молодец.'); }; }
Никогда не используйте аргумент функции
arguments
, он будет более приоритетным над объектомarguments
, который доступен без объявления для каждой функции.// плохо function nope(name, options, arguments) { // ...код... } // хорошо function yup(name, options, args) { // ...код... }
Свойства
Используйте точечную нотацию для доступа к свойствам и методам.
var luke = { jedi: true, age: 28 }; // плохо var isJedi = luke['jedi']; // хорошо var isJedi = luke.jedi;
Используйте нотацию с
[]
, когда вы получаете свойство, имя для которого хранится в переменной.var luke = { jedi: true, age: 28 }; function getProp(prop) { return luke[prop]; } var isJedi = getProp('jedi');
Переменные
Всегда используйте
var
для объявления переменных. В противном случае переменная будет объявлена глобальной. Загрязнение глобального пространства имен — всегда плохо.// плохо superPower = new SuperPower(); // хорошо var superPower = new SuperPower();
Используйте одно
var
объявление переменных для всех переменных, и объявляйте каждую переменную на новой строке.// плохо var items = getItems(); var goSportsTeam = true; var dragonball = 'z'; // хорошо var items = getItems(), goSportsTeam = true, dragonball = 'z';
Объявляйте переменные, которым не присваивается значение, в конце. Это удобно, когда вам необходимо задать значение одной из этих переменных на базе уже присвоенных значений.
// плохо var i, len, dragonball, items = getItems(), goSportsTeam = true; // плохо var i, items = getItems(), dragonball, goSportsTeam = true, len; // хорошо var items = getItems(), goSportsTeam = true, dragonball, length, i;
Присваивайте переменные в начале области видимости. Это помогает избегать проблем с объявлением переменных и областями видимости.
// плохо 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; }
Области видимости
Объявление переменных ограничивается областью видимости, а присвоение — нет.
// Мы знаем, что это не будет работать // если нет глобальной переменной notDefined function example() { console.log(notDefined); // => выбрасывает код с ошибкой ReferenceError } // Декларирование переменной после ссылки на нее // не будет работать из-за ограничения области видимости. function example() { console.log(declaredButNotAssigned); // => undefined var declaredButNotAssigned = true; } // Интерпретатор переносит объявление переменной // к верху области видимости. // Что значит, что предыдущий пример в действительности // будет воспринят интерпретатором так: function example() { var declaredButNotAssigned; console.log(declaredButNotAssigned); // => undefined declaredButNotAssigned = true; }
Объявление анонимной функции поднимает наверх области видимости саму переменную, но не ее значение.
function example() { console.log(anonymous); // => undefined anonymous(); // => TypeError anonymous is not a function // Ошибка типов: переменная anonymous не является функцией и не может быть вызвана var anonymous = function() { console.log('анонимная функция'); }; }
Именованные функции поднимают наверх области видимости переменную, не ее значение. Имя функции при этом недоступно в области видимости переменной и доступно только изнутри.
function example() { console.log(named); // => undefined named(); // => TypeError named is not a function // Ошибка типов: переменная named не является функцией и не может быть вызвана superPower(); // => ReferenceError superPower is not defined (Ошибка ссылки: переменная superPower не найдена в этой области видимости) var named = function superPower() { console.log('Я лечууууу'); }; } // То же самое происходит, когда имя функции и имя переменной совпадают. // var named доступно изнутри области видимости функции example. // function named доступна только изнутри ее самой. function example() { console.log(named); // => undefined named(); // => TypeError named is not a function // Ошибка типов: переменная named не является функцией и не может быть вызвана var named = function named() { console.log('именованная функция'); } }
Объявления функции поднимают на верх текущей области видимости и имя, и свое значение.
function example() { superPower(); // => Я лечууууу function superPower() { console.log('Я лечууууу'); } }
Более подробно можно прочитать в статье JavaScript Scoping & Hoisting от Ben Cherry
Условные выражения и равенства
- Используйте
===
и!==
вместо==
и!=
. Условные выражения вычисляются посредством приведения к логическому типу Boolean через метод
ToBoolean
и всегда следуют следующим правилам:- Object всегда соответствует true
- Undefined всегда соответствует false
- Null всегда соответствует false
- Boolean остается неизменным
- Number соответствует false, если является +0, -0, или NaN, в противном случае соответствует true
- String означает false, если является пустой строкой
''
, в противном случае true. Условно говоря, для строки происходит сравнение не ее самой, а ее длины – в соответствии с типом number.
if ([0]) { // true // Массив(Array) является объектом, объекты преобразуются в true }
Используйте короткий синтаксис.
// плохо if (name !== '') { // ...код... } // хорошо if (name) { // ...код... } // плохо if (collection.length > 0) { // ...код... } // хорошо if (collection.length) { // ...код... }
Более подробно можно прочитать в статье Truth Equality and JavaScript от Angus Croll
Блоки кода
Используйте фигурные скобки для всех многострочных блоков.
// плохо if (test) return false; // хорошо if (test) return false; // хорошо if (test) { return false; } // плохо function() { return false; } // хорошо function() { return false; }
Комментарии
Используйте
/** ... */
для многострочных комментариев. Включите описание, опишите типы и значения для всех параметров и возвращаемых значений в формате jsdoc.// плохо // make() возвращает новый элемент // основываясь на получаемом имени тэга // // @param <String> tag // @return <Element> element function make(tag) { // ...создаем element... return element; } // хорошо /** * make() возвращает новый элемент * основываясь на получаемом имени тэга * * @param <String> tag * @return <Element> element */ function make(tag) { // ...создаем element... return element; }
Используйте
//
для комментариев в одну строку. Размещайте комментарии на новой строке над темой комментария. Добавляйте пустую строку над комментарием.// плохо var active = true; // устанавливаем активным элементом // хорошо // устанавливаем активным элементом var active = true; // плохо function getType() { console.log('проверяем тип...'); // задаем тип по умолчанию 'no type' var type = this._type || 'no type'; return type; } // хорошо function getType() { console.log('проверяем тип...'); // задаем тип по умолчанию 'no type' var type = this._type || 'no type'; return type; }
Префикс
TODO
помогает другим разработчикам быстро понять, что вы указываете на проблему, к которой нужно вернуться в дальнейшем, или если вы предлагете решение проблемы, которое должно быть реализовано. Эти комментарии отличаются от обычных комментариев, так как не описывают текущее поведение, а призывают к действию, напримерTODO -- нужно реализовать интерфейс
. Такие комментарии также автоматически обнаруживаются многими IDE и редакторами кода, что позволяет быстро перемещаться между ними.Используйте
// TODO FIXME:
для аннотирования проблемfunction Calculator() { // TODO FIXME: тут не нужно использовать глобальную переменную total = 0; return this; }
Используйте
// TODO:
для указания решений проблемfunction Calculator() { // TODO: должна быть возможность изменять значение через параметр функции this.total = 0; return this; }
Пробелы
Используйте программную табуляцию (ее поддерживают все современные редакторы кода и IDE) из двух пробелов.
// плохо 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' });
Оставляйте новую строку в конце файла.
// плохо (function(global) { // ...код... })(this);
// хорошо (function(global) { // ...код... })(this);
Используйте отступы, когда делаете цепочки вызовов.
// плохо $('#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' };
Дополнительная запятая в конце объектов: Нет. Она способна вызвать проблемы с IE6/7 и IE9 в режиме совместимости. В некоторых реализациях ES3 запятая в конце массива увеличивает его длину на 1, что может вызвать проблемы. Этот вопрос был прояснен только в ES5 (оригинал):
Редакция ECMAScript 5 однозначно устанавливает факт, что запятая в конце ArrayInitialiser не должна увеличивать длину массива. Это несемантическое изменение от Редакции ECMAScript 3, но некоторые реализации до этого некорректно разрешали этот вопрос.
// плохо var hero = { firstName: 'Kevin', lastName: 'Flynn', }; var heroes = [ 'Batman', 'Superman', ]; // хорошо var hero = { firstName: 'Kevin', lastName: 'Flynn' }; var heroes = [ 'Batman', 'Superman' ];
Точки с запятой
Да.
// плохо (function() { var name = 'Skywalker' return name })() // хорошо (function() { var name = 'Skywalker'; return name; })(); // хорошо ;(function() { var name = 'Skywalker'; return name; })();
Приведение типов
- Выполняйте приведение типов в начале операции, но не делайте его избыточным.
Строки:
// => this.reviewScore = 9; // плохо var totalScore = this.reviewScore + ''; // хорошо var totalScore = '' + this.reviewScore; // плохо var totalScore = '' + this.reviewScore + ' итого'; // хорошо var totalScore = this.reviewScore + ' итого';
Используйте
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
тратится больше всего ресурсов, используйте побитовый сдвиг из соображений быстродействия, но обязательно оставьте комментарий с объяснением причин.// хорошо /** * этот код медленно работал из-за parseInt * побитовый сдвиг строки для приведения ее к числу * работает значительно быстрее. */ var val = inputValue >> 0;
Примечание: Будьте осторожны с побитовыми операциями. Числа в JavaScript являются 64-битными значениями, но побитовые операции всегда возвращают 32-битные значенения. Источник. Побитовые операции над числами, значение которых выходит за 32 бита (верхний предел: 2,147,483,647).
2147483647 >> 0 //=> 2147483647 2147483648 >> 0 //=> -2147483648 2147483649 >> 0 //=> -2147483647
логические типы(Boolean):
var age = 0; // плохо var hasAge = new Boolean(age); // хорошо var hasAge = Boolean(age); // хорошо var hasAge = !!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' });
Используйте PascalCase для именования конструкторов классов
// плохо function user(options) { this.name = options.name; } var bad = new user({ name: 'Плохиш' }); // хорошо function User(options) { this.name = options.name; } var good = new User({ name: 'Кибальчиш' });
Используйте подчеркивание
_
в качестве префикса для именования внутренних методов и переменных объекта.// плохо this.__firstName__ = 'Panda'; this.firstName_ = 'Panda'; // хорошо this._firstName = 'Panda';
Создавая ссылку на
this
, используйте_this
.// плохо function() { var self = this; return function() { console.log(self); }; } // плохо function() { var that = this; return function() { console.log(that); }; } // хорошо function() { var _this = this; return function() { console.log(_this); }; }
Задавайте имена для функций. Это повышает читаемость сообщений об ошибках кода.
// плохо 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-событиям, так и js-событиям, например, в Backbone), передавайте объект вместо простой переменной. Это позволяет в процессе всплытия событий добавлять к данному объекту дополнительную информацию.
// плохо $(this).trigger('listingUpdated', listing.id); ... $(this).on('listingUpdated', function(e, listing) { //делаем что-нибудь с listing, например: listing.name = listings[listing.id] });
prefer:
// хорошо $(this).trigger('listingUpdated', { listingId : listing.id }); ... $(this).on('listingUpdated', function(e, data) { // делаем что-нибудь с 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
Для jQuery-переменных используйте префикс
$
.// плохо var sidebar = $('.sidebar'); // хорошо var $sidebar = $('.sidebar');
Кэшируйте jQuery-запросы. Каждый новый jQuery-запрос делает повторный поиск по DOM-дереву, и приложение начинает работать медленнее.
// плохо function setSidebar() { $('.sidebar').hide(); // ...код... $('.sidebar').css({ 'background-color': 'pink' }); } // хорошо function setSidebar() { var $sidebar = $('.sidebar'); $sidebar.hide(); // ...код... $sidebar.css({ 'background-color': 'pink' }); }
Для DOM-запросов используйте классический каскадный CSS-синтаксис
$('.sidebar ul')
или родитель > потомок$('.sidebar > ul')
. jsPerfИспользуйте
find
для поиска внутри DOM-объекта.// плохо $('ul', '.sidebar').hide(); // плохо $('.sidebar').find('ul').hide(); // хорошо $('.sidebar ul').hide(); // хорошо $('.sidebar > ul').hide(); // хорошо $sidebar.find('ul');
Совместимость ECMAScript 5
Опирайтесь на таблицу совместимости с ES5 от Kangax
Тестирование
Да.
function() { return true; }
Быстродействие
- On Layout & Web Performance
- String vs Array Concat
- Try/Catch Cost In a Loop
- Bang Function
- jQuery Find vs Context, Selector
- innerHTML vs textContent for script text
- Long String Concatenation
В процессе наполнения...
Ресурсы
Прочитайте это
Другие руководства по стилю
- Google JavaScript Style Guide
- jQuery Core Style Guidelines
- Principles of Writing Consistent, Idiomatic JavaScript
Другие стили
- Naming this in nested functions - Christian Johansen
- Conditional Callbacks
- Popular JavaScript Coding Conventions on Github
Дальнейшее прочтение
- Understanding JavaScript Closures - Angus Croll
- Basic JavaScript for the impatient programmer - Dr. Axel Rauschmayer
Книги
- JavaScript: The Good Parts - Douglas Crockford
- JavaScript Patterns - Stoyan Stefanov
- Pro JavaScript Design Patterns - Ross Harmes and Dustin Diaz
- High Performance Web Sites: Essential Knowledge for Front-End Engineers - Steve Souders
- Maintainable JavaScript - Nicholas C. Zakas
- JavaScript Web Applications - Alex MacCaw
- Pro JavaScript Techniques - John Resig
- Smashing Node.js: JavaScript Everywhere - Guillermo Rauch
- Secrets of the JavaScript Ninja - John Resig and Bear Bibeault
- Human JavaScript - Henrik Joreteg
- Superhero.js - Kim Joar Bekkelund, Mads Mobæk, & Olav Bjorkoy
- JSBooks
Блоги
- DailyJS
- JavaScript Weekly
- JavaScript, JavaScript...
- Bocoup Weblog
- Adequately Good
- NCZOnline
- Perfection Kills
- Ben Alman
- Dmitry Baranovskiy
- Dustin Diaz
В реальном мире
Вот неполный список организаций, которые опираются на оригинальное руководство от AirBnB. Если вы собираетесь использовать это переведенное руководство, сделайте pull request, и мы сможем начать отдельный список компаний, использующих данный перевод.
- Aan Zee: AanZee/javascript
- Airbnb: airbnb/javascript
- Compass Learning: compasslearning/javascript-style-guide
- ExactTarget: ExactTarget/javascript
- Gawker Media: gawkermedia/javascript
- GeneralElectric: GeneralElectric/javascript
- GoodData: gooddata/gdc-js-style
- Grooveshark: grooveshark/javascript
- How About We: howaboutwe/javascript
- Mighty Spring: mightyspring/javascript
- MinnPost: MinnPost/javascript
- ModCloth: modcloth/javascript
- National Geographic: natgeo/javascript
- Razorfish: razorfish/javascript-style-guide
- Shutterfly: shutterfly/javascript
- Zillow: zillow/javascript
- ZocDoc: ZocDoc/javascript