- Общие положения
- Именование
- Объявление переменных
- Литералы
- Точка с запятой
- Ключевые слова
- Блочные инструкции
- Условные инструкции
- Циклы
- Операторы
- eval
- undefined
- Круглые скобки
- Исключения
- Приведение типов
- Переносы строк
- Цепочки вызовов
- Конкатенация строк
- Пустые линии
- Контекст функции
- Комментарии
- Классы
- node.js
- Кодировка UTF-8 без BOM.
- Перевод строки: LF. В конце файла перевод строки обязателен.
- Отступ 4 пробела, знаки табуляции не применяются.
- Длина линии не должна превышать 120 символов.
- Нет лишних пробелов в конце строк (настраиваем свой текстовый редактор, чтобы он удалял лишние пробелы при сохранении).
variableNamesLikeThis
functionNamesLikeThis
functionArgumentsLikeThis
ClassNamesLikeThis
methodNamesLikeThis
CONSTANTS_LIKE_THIS
namespaceLikeThis
event-like-this
private
свойства и методы объектов начинаются с подчеркивания_
protected
свойства и методы объектов также начинаются с подчеркивания_
- Избегаем коротких или немногословных названий
- В именовании аббревиатур соблюдаем
CamelCase
. Например:Json
,Xml
.
- Все переменные объявляются с
var
. - Каждая переменная в пределах одной области видимости объявляется только один раз.
- Каждая переменная объявляется на новой строке. Это позволяет легко менять строки местами и подписывать к ним комментарии.
- Переменные объявляются как можно ближе к месту использования.
Хорошо:
var keys = ['foo', 'bar'];
var values = [23, 42];
var object = {};
while (items.length) {
var key = keys.pop();
object[key] = values.pop();
}
Плохо:
var keys = ['foo', 'bar'],
values = [23, 42],
object = {},
key;
while (items.length) {
key = keys.pop();
object[key] = values.pop();
}
- После открывающей фигурной скобки и перед закрывающей пробел не ставится:
var obj = {a: 1, b: 2, c: 3};
this.method({a: 1, b: 2});
- Пробел перед двоеточием не ставится:
var obj = {
prop: 0
};
- Выравнивание не используется:
Хорошо:
var obj = {
a: 0,
b: 1,
lengthyName: 2
};
Плохо:
var obj = {
a : 0,
b : 1,
lengthyName: 2
};
- Имена ключей заключаются в кавычки только по необходимости:
Хорошо:
var obj = {
key: 0,
'key-key': 1
};
Плохо:
var obj = {
'key': 0,
'key-key': 1
};
При объявлении массива, пробел ставится лишь после запятой:
var fellowship = ['foo', 'bar', 'baz'];
- Строки записываются с использованием одинарных кавычек:
var lyrics = 'Never gonna give you up, Never gonna let you down';
- Если в строке встречается одинарная кавычка, она экранируется:
var test = 'It shouldn\'t fail';
##Точка с запятой Точка с запятой ставится всегда.
- Ключевые слова отделяются пробелом:
if (test) {
// ...
}
function foo() {
// ...
}
var bar = function () {
// ...
};
- Перед точкой с запятой пробел не ставится:
return;
- Открывающая фигурная скобка ставится на той же строке и отделяется пробелом от предыдущей конструкции:
if (test) {
// ...
}
function foo() {
// ...
}
- Фигурные скобки ставятся всегда:
Хорошо:
if (test) {
return;
}
Плохо:
if (test)
return;
if (test) return;
if (test) { return; }
else
пишется на той же строке, что и закрывающая фигурная скобка
if (test) {
// ...
} else {
// ...
}
- Присваивание в условном выражении не используется:
Хорошо:
var foo = bar();
if (foo > 0) {
// ...
}
Плохо:
var foo;
if ((foo = bar()) > 0) {
// ...
}
- Выражения используются только там, где требуется значение:
Хорошо:
if (condition) {
actionIfTrue();
} else {
actionIfFalse();
}
Плохо:
condition && actionIfTrue() || actionIfFalse();
- Длинные условия, которые не вмещаются на одну строку, разбиваются следующим образом:
if (longCondition ||
anotherLongCondition &&
yetAnotherLongCondition
) {
// ...
}
- Yoda conditions не используются:
Хорошо:
if (getType() === 'driving') {
}
Плохо:
if ('driving' === getType()) {
}
switch (value) {
case 1:
// ...
break;
case 2:
// ...
break;
default:
// ...
// no break keyword on the last case
}
##Циклы
###for
По возможности вместо for
используется Array.prototype.forEach:
[1, 2, 3].forEach(function (value) {
console.log(value);
});
Код с использованием forEach
проще читать (легче абстрагироваться от того, что происходит в каждой итерации). Где
критична скорость используется обычный for
.
###for (var i in obj)
По возможности вместо for-in
используется Object.keys:
Object.keys(obj).forEach(function (key) {
console.log(key);
});
Оператор with
не используется.
###Оператор равенства
Всегда используется строгое равенство ===
(неравенство !==
), если нет необходимости в приведении типов.
var x = a ? b : c;
var y = a ?
longButSimpleOperandB : longButSimpleOperandC;
var z = a ?
moreComplicatedB :
moreComplicatedC;
###Унарный оператор Все унарные операторы пишутся слитно с операндами:
var foo = !bar;
##eval
Избегаем использования eval
. Для парсинга json
используется JSON.parse.
Проверяем значение через строгое сравнение.
Хорошо:
x === undefined;
Плохо:
// в современных браузерах уже определен immutable undefined.
var undefined;
x === undefined;
// больше писать
typeof x === 'undefined'
x === void 0
- Ставятся, если только это необходимо синтаксисом или семантикой.
- Не используются с унарными операторами
delete
,typeof
иvoid
, а также ключевыми словамиreturn
,throw
,new
.
Создаём исключения с помощью new Error
:
Хорошо:
throw new Error('msg');
Плохо:
throw 'msg';
Используются явные приведения типов:
Хорошо:
Boolean(foo)
Number(bar)
String(baz)
[].indexOf(qux) === -1 или [].indexOf(qux) < 0
Плохо:
!!foo
+bar
baz + ''
~[].indexOf(qux)
- Максимальная длина строки
120
символов, если строка выходит длиннее, то по возможности делаются переносы строки, с соответствующими отступами после переноса. - Операторы размещаются на предыдущей строке:
var debt = this.calculateBaseDebt() + this.calculateSharedDebt() + this.calculateDebtPayments() +
this.calculateDebtFine();
- Закрывающие скобки не прижимаются к переносимому коду:
Хорошо:
DoSomethingThatRequiresALongFunctionName(
veryLongArgument1,
argument2,
argument3,
argument4
);
anotherStatement;
Плохо:
DoSomethingThatRequiresALongFunctionName(
veryLongArgument1,
argument2,
argument3,
argument4);
anotherStatement;
- При переносе вызова функции на новую строку:
- Оператор доступа к свойству
.
ставится на новой строке. - Добавляется отступ относительно объекта, у которого вызывается функция.
- Оператор доступа к свойству
Хорошо:
someObject
.operation()
.operationWithCallback(function (obj) {
obj.processed = true;
})
.end();
Плохо:
someObject.
start().
end();
someObject
.start()
.end();
- Для конкатенации строк используется оператор
+
. - Конструкция
[].join('')
не используется (это было актуально для старых браузеров). \
не используется.
Хорошо:
var foo = 'A rather long string of English text, an error message ' +
'actually that just keeps going and going -- an error ' +
'message to make the Energizer bunny blush (right through ' +
'those Schwarzenegger shades)! Where was I? Oh yes, ' +
'you\'ve got an error and all the extraneous whitespace is ' +
'just gravy. Have a nice day.';
Плохо:
var foo = 'A rather long string of English text, an error message \
actually that just keeps going and going -- an error \
message to make the Energizer bunny blush (right through \
those Schwarzenegger shades)! Where was I? Oh yes, \
you\'ve got an error and all the extraneous whitespace is \
just gravy. Have a nice day.';
##Пустые линии Могут использоваться для логической группировки частей кода:
doSomethingTo(x);
doSomethingElseTo(x);
andThen(x);
nowDoSomethingWith(y);
andNowWith(z);
- Рекомендуется использовать
Function.prototype.bind
:
doAsync(function () {
this.fn();
}.bind(this));
- Если функция позволяет передать
this
параметром, используем его:
Хорошо:
[1, 2, 3].forEach(function (n) {
this.fn(n);
}, this);
Плохо:
[1, 2, 3].forEach(function (n) {
this.fn(n);
}.bind(this));
- Если используется переменная, называем ее
_this
:
var _this = this;
doAsync(function () {
_this.fn();
});
- Для инлайновых комментариев используется
//
. После//
ставится 1 пробел. - Комментарии к функциям, классам и т.п. пишутся в формате jsdoc.
##Классы "Симметричные" методы размещаем рядом. Например:
var FooClass = inherit({
__constructor: function () {},
// деструктор рядом с конструктором
destruct: function () {},
someMethod: function () {}
});
- Все модули импортируются в начале файла сразу после описания к нему, если оно есть:
Хорошо:
var http = require('http');
var fs = require('fs');
// code here
Плохо:
var http = require('http');
// code here
var fs = require('fs');
// code here
Исключение: модули, импортируемые по требованию.
- Импорты должны быть сгруппированы в следующем порядке:
- стандартные модули node.js
- модули сторонних библиотек
- модули вашего приложения