Стиль, который вы выбираете для своего проекта, должен быть самым высоким критерием. Поместите его в качестве описания в свой проект и свяжите его с этим документом как гарантию согласованности, читаемости и обслуживаемости стиля кода.
1. Бланк
1. Никогда не смешивайте места и вкладки.
2. Начните проект, выберите Soft Adent (Space) или вкладку (в качестве метода отступления) перед написанием кода и используйте его в качестве самого высокого критерия.
а). Для читаемости я всегда рекомендую разработать 2 -буквенную ширину в ваших редакторах - это эквивалентно двум местам или двум пространствам вместо вкладки.
3. Если ваш редактор поддерживает его, всегда включайте настройку «Показать невидимые символы». Преимущества:
а). Обеспечить последовательность
б). Снимите пространства в конце линии
в). Удалить пробелы
г). Представление и сравнение более читаемые
2. Украсить грамматику
A. Брекеты, брекеты, разрывы линий
Кода -копия выглядит следующим образом:
// if/else/for/while/try обычно имеют скобки, кудрявые скобки и несколько линий
// это помогает читаемо
// 2.A.1.1
// Пример сложного синтаксиса
if (условие) dosomething ();
в то время как (условие) итерация ++;
для (var i = 0; i <100; i ++) aeTherativeFn ();
// 2.A.1.1
// Использование пространств для улучшения читаемости
if (условие) {
// Заявление
}
while (условие) {
// Заявление
}
для (var i = 0; i <100; i ++) {
// Заявление
}
// Лучшая практика:
var i,
длина = 100;
for (i = 0; i <length; i ++) {
// Заявление
}
// или...
var i = 0,
длина = 100;
for (; i <length; i ++) {
// Заявление
}
var prop;
для (rop in object) {
// Заявление
}
if (true) {
// Заявление
} еще {
// Заявление
}
B. Назначение, объявление, функция (именованные функции, выражения функций, функции конструктора)
Кода -копия выглядит следующим образом:
// 2.b.1.1
// Переменная
var foo = "bar",
num = 1,
Undef;
// буквальная идентификация:
var array = [],
Object = {};
// 2.b.1.2
// Использование только одного `var` в рамках (функция) помогает улучшить читаемость
// и сделайте свой список операторов упорядочен (также сохраняет вам несколько типинг клавиатуры)
// не хорошо
var foo = "";
var bar = "";
var qux;
// хороший
var foo = "",
bar = "",
Quux;
// или..
var // комментирует эти переменные
foo = "",
bar = "",
Quux;
// 2.b.1.3
// оператор `var` всегда должен быть в верхней части каждой области (функция)
// также подходит для постоянных из Ecmascript 6
// не хорошо
функция foo () {
// есть оператор перед переменной
var bar = "",
qux;
}
// хороший
функция foo () {
var bar = "",
qux;
// Все операторы после переменной
}
// 2.B.2.1
// Объявление о именованной функции
функция foo (arg1, argn) {
}
// Как использовать
foo (arg1, argn);
// 2.b.2.2
// Объявление о именованной функции
Функция Square (номер) {
возвратный номер * номер;
}
// Как использовать
квадрат (10);
// очень неестественный стиль прохождения прохождения
Функция Square (номер, обратный вызов) {
обратный вызов (номер * номер);
}
квадрат (10, функция (квадрат) {
// Контент обратного вызова
});
// 2.B.2.3
// Функция выражения
var square = function (номер) {
// Возврат ценного и соответствующего контента
возвратный номер * номер;
};
// Экспрессия функции с идентификатором
// Эта предпочтительная форма имеет дополнительные функции, которые позволяют ей вызвать
// и в стеке есть идентификатор
var factorial = function factorial (число) {
if (номер <2) {
возврат 1;
}
возвратный номер * фактор (номер-1);
};
// 2.B.2.4
// объявление конструктора
Функция foobar (опции) {
this.options = options;
}
// Как использовать
var foobar = new foobar ({a: "alpha"});
foobar.options;
// {a: "alpha"}
C. Исключение, детали
Кода -копия выглядит следующим образом:
// 2.C.1.1
// функции с обратными вызовами
foo (function () {
// Примечание: в скобках нет мест и `function 'первого вызова функции
});
// Функция принимает `Array` в качестве аргумента, без пробелов
foo (["alpha", "beta"]);
// 2.C.1.2
// функция принимает `object` в качестве аргумента, без пробелов
foo ({
A: "Альфа",
Б: «Бета»
});
// Функция принимает буквальную буква
foo ("bar");
// Внутри скобков нет мест, используемых для группировки
if (! ("foo" в obj)) {
}
D. Последовательность всегда побеждает
В разделах 2.A-2.C пустое пространство предлагается в качестве метода рекомендаций, основанный на простой, более высокой цели: объединение. Стоит отметить, что предпочтения форматирования, такие как «внутреннее пустое пространство», должны быть необязательными, но должен быть только один тип исходного кода всего проекта.
Кода -копия выглядит следующим образом:
// 2.d.1.1
if (условие) {
// Заявление
}
while (условие) {
// Заявление
}
для (var i = 0; i <100; i ++) {
// Заявление
}
if (true) {
// Заявление
} еще {
// Заявление
}
E. Цитаты
Неважно, выбираете ли вы одиночные или двойные цитаты, они не имеют разницы в JavaScript. Что абсолютно должно быть обязательным, так это последовательность. Никогда не смешивайте две цитаты в одном и том же проекте, выбирайте одну и держите его в соответствии.
F. Конец линии и пустой линии
Уход пробел сломает разницу, а использование изменений нечитаемы. Подумайте о том, чтобы включить предварительно заполненный крючок, который автоматически удаляет пространства в конце линии и пустых линий.
3. Обнаружение типа (из руководящих принципов основного стиля jQuery)
A. Прямой тип (фактический тип, фактический тип)
Нить:
Кода -копия выглядит следующим образом:
typeof variable === "String"
Число:
Кода -копия выглядит следующим образом:
typeof variable === "номер"
Логическое:
Кода -копия выглядит следующим образом:
typeof variable === "Boolean"
Объект:
Кода -копия выглядит следующим образом:
typeof variable === "Объект"
Множество:
Кода -копия выглядит следующим образом:
Array.isarray (ArraylikeObject)
(Если возможно)
Узел:
Кода -копия выглядит следующим образом:
elem.nodeType === 1
нулевой:
Кода -копия выглядит следующим образом:
переменная === NULL
нулевой или неопределенный:
Кода -копия выглядит следующим образом:
переменная == NULL
неопределенный:
Глобальные переменные:
Кода -копия выглядит следующим образом:
typeof variable === "не определен"
Локальные переменные:
Кода -копия выглядит следующим образом:
переменная === не определен
свойство:
Кода -копия выглядит следующим образом:
Object.prop === не определен
object.hashownproperty (prop)
«Опора» в объекте
B. Конвертировать тип (тип принуждения, принудительные типы)
Рассмотрим значение следующего ...
Учитывая HTML:
Кода -копия выглядит следующим образом:
<input type = "text" id = "foo-input" value = "1">
// 3.b.1.1
// `foo` было назначено значение` 0`, введите `number`
var foo = 0;
// typeof foo;
// "число"
...
// В последующем коде необходимо обновить `foo` и присвоить новое значение, полученное в входном элементе
foo = document.getElementbyId ("foo-input"). value;
// Если вы тестируете `typeof foo` сейчас, результат будет` string '
// это означает, что у вас есть логика, похожая на это при обнаружении `foo` в операторе if:
if (foo === 1) {
важный раз ();
}
// `QuartyTask ()` никогда не будет выполнен, даже если `foo` имеет значение" 1 "
// 3.b.1.2
// Вы можете умело использовать +/- Unary Operator, чтобы выбрать тип для решения проблемы:
foo = +document.getElementbyId ("foo-input"). value;
// ^ + Unary Operator преобразует объект операции в его право в `number`
// typeof foo;
// "число"
if (foo === 1) {
важный раз ();
}
// `QuartyTask ()` будет называться
Вот несколько примеров для кастинга:
Кода -копия выглядит следующим образом:
// 3.b.2.1
var number = 1,
string = "1",
bool = false;
число;
// 1
номер + "";
// "1"
нить;
// "1"
+строка;
// 1
+string ++;
// 1
нить;
// 2
Bool;
// ЛОЖЬ
+bool;
// 0
Bool + "";
// "ЛОЖЬ"
// 3.b.2.2
var number = 1,
string = "1",
bool = true;
string === номер;
// ЛОЖЬ
string === номер + "";
// истинный
+string === номер;
// истинный
bool === номер;
// ЛОЖЬ
+bool === номер;
// истинный
bool === String;
// ЛОЖЬ
bool === !! String;
// истинный
// 3.b.2.3
var array = ["a", "b", "c"];
!! ~ array.indexof ("a");
// истинный
!! ~ array.indexof ("b");
// истинный
!! ~ array.indexof ("c");
// истинный
!! ~ array.indexof ("D");
// ЛОЖЬ
// Стоит отметить, что все вышеупомянутые «ненужные умные»
// Используйте четкую схему для сравнения возвращенных значений
// Например, индекс:
if (array.indexof ("a")> = 0) {
// ...
}
// 3.b.2.3
var num = 2,5;
Parseint (num, 10);
// эквивалентно ...
~~ num;
num >> 0;
num >>> 0;
// все результаты 2
// Всегда помните, отрицательные значения будут относиться по -разному ...
var neg = -2,5;
Parseint (нег, 10);
// эквивалентно ...
~~ нега;
нег >> 0;
// все результаты -2
// но...
нег >>> 0;
// Результат 4294967294
4. Сравнительные операции
Кода -копия выглядит следующим образом:
// 4.1.1
// Когда просто судить о том, имеет ли массив длиной, относительно использования этого:
if (array.length> 0) ...
// ... Чтобы определить подлинность, используйте это:
if (array.length) ...
// 4.1.2
// Когда просто судить, является ли массив пустым, относительно использования этого:
if (array.length === 0) ...
// ... Чтобы определить подлинность, используйте это:
if (! array.length) ...
// 4.1.3
// Когда просто судить о том, пуста ли строка, относительно использования этого:
if (String! == "") ...
// ... Чтобы определить подлинность, используйте это:
if (String) ...
// 4.1.4
// Когда просто судить, что строка пуста, относительно использования этого:
if (String === "") ...
// ... Чтобы определить подлинность, используйте это:
if (! String) ...
// 4.1.5
// Когда просто судить, что ссылка верна, по сравнению с использованием этого:
if (foo === true) ...
// ... судить, как вы думаете, наслаждайтесь преимуществами встроенных функций:
if (foo) ...
// 4.1.6
// Когда просто судить, что ссылка является ложной, относительно использования этого:
if (foo === false) ...
// ... конвертировать его в True, используя восклицательный знак
if (! foo) ...
// ... Следует отметить, что это будет соответствовать 0, ", нулевой, неопределенный, NAN
// Если вы _must_ - логический тип false, используйте это:
if (foo === false) ...
// 4.1.7
// Если вы хотите рассчитать ссылку, она может быть нулевой или неопределенной, но это не ложно, "или 0,
// относительно использования этого:
if (foo === null || foo === не определен) ...
// ... наслаждайтесь преимуществами кастинга типа ==, например:
if (foo == null) ...
// Помните, что использование == сделает `null` match` null` и `undefined '
// но не `false`," или 0
null == не определен
Всегда судите лучшие и наиболее точные ценности, приведенное выше - это руководство, а не догма.
Кода -копия выглядит следующим образом:
// 4.2.1
// Инструкции по операциям по конверсии и сравнению типа
// В первый раз `===`, `==` следовали (если не требуется сравнение свободного типа)
// `===` не всегда делает преобразование типа, что означает:
"1" === 1;
// ЛОЖЬ
// `==` преобразует тип, что означает:
"1" == 1;
// истинный
// 4.2.2
// логический, правдивый и фальшивый
// boolean:
Правда, ложь
// настоящий:
"Foo", 1
// псевдо:
", 0, нулевой, неопределенный, нан, пустота 0
5. Практический стиль
Кода -копия выглядит следующим образом:
// 5.1.1
// практический модуль
(function (Global) {
var module = (function () {
var data = "secret";
возвращаться {
// это логическое значение
Bool: Правда,
// строка
строка: "строка",
// массив
массив: [1, 2, 3, 4],
// объект
объект: {
Ланг: "en-us"
},
getData: function () {
// Получить значение `data '
вернуть данные;
},
setData: function (value) {
// Возврат назначенного значения `data '
return (data = value);
}
};
}) ();
// некоторые другие появятся здесь
// превратить свой модуль в глобальный объект
Global.Module = MODULE;
})( этот );
// 5.2.1
// практическая функция сборки
(function (Global) {
функция ctor (foo) {
this.foo = foo;
вернуть это;
}
Ctor.prototype.getfoo = function () {
вернуть это.foo;
};
Ctor.prototype.setfoo = function (val) {
return (this.foo = val);
};
// не используйте `new`, чтобы вызвать функцию сборки, вы можете сделать это:
varctor = function (foo) {
вернуть новый ctor (foo);
};
// превратить нашу функцию сборки в глобальный объект
Global.ctor = ctor;
})( этот );
6. Наименование
О. Вы не являетесь человеческим компилятором/компрессором, поэтому постарайтесь превратиться в один.
Следующий код является примером очень плохого именования:
Кода -копия выглядит следующим образом:
// 6.A.1.1
// Плохое пример именования кода
функция q (s) {
return Document.queryselectorall (ы);
}
var i, a = [], els = q ("#foo");
for (i = 0; i <els.length; i ++) {a.push (els [i]);}
Нет сомнений в том, что вы написали такой код - надеюсь, он не появится снова с сегодняшнего дня.
Вот код с той же логикой, но с более надежным, удачным именованием (и читаемой структурой):
Кода -копия выглядит следующим образом:
// 6.A.2.1
// Улучшенный именованный пример кода
Функциональный запрос (селектор) {
return document.queryselectorall (селектор);
}
var idx = 0,
элементы = [],
matches = Query ("#foo"),
длина = совпадает.length;
for (; idx <length; idx ++) {
elements.push (соответствует [idx]);
}
Некоторые дополнительные советы по имени:
Кода -копия выглядит следующим образом:
// 6.A.3.1
// с именем строки
`Dog` - это струна
// 6.A.3.2
// имен массивы
`['Dogs']` - это массив, содержащий `Dog String
// 6.A.3.3
// именные функции, объекты, экземпляры и т. Д.
Camlcase; Функция и объявления VAR
// 6.A.3.4
// Назовите строитель, прототип и т. Д.
Pascalcase; построить функцию
// 6.A.3.5
// Назовите регулярные выражения
rdesc = //;
// 6.A.3.6
// Руководство по библиотеке Google Library Guide
functionnameslikethis;
variablenameslikethis;
ConstructorNamesLikethis;
Enumnameslikethis;
Methodnameslikethis;
Symbolic_constants_like_this;
Б. Посмотрите на это
В дополнение к использованию хорошо известного вызова и применения, .bind (this) или функционально эквивалентный для него всегда предпочтительнее. Создайте объявление о пограничной функции для последующих вызовов, используя псевдоним, когда нет лучшего варианта.
Кода -копия выглядит следующим образом:
// 6.B.1
Функциональное устройство (Opts) {
this.value = null;
// Создать новый асинхронный поток, это будет постоянно вызвать
stream.read (opts.path, function (data) {
// Использование потока, чтобы вернуть последнее значение данных и обновить значение экземпляра
this.value = data;
} .bind (this));
// управлять частотой запуска событий
setInterval (function () {
// опубликовать контролируемое событие
this.emit ("Event");
} .bind (this), opts.freq || 100);
}
// Предположим, мы унаследовали Eventemitter;)
Когда его нельзя запустить, эквивалент .Bind доступен в большинстве современных библиотек JavaScript.
Кода -копия выглядит следующим образом:
// 6.B.2
// Пример: Lodash/Underscore, _.bind ()
Функциональное устройство (Opts) {
this.value = null;
stream.read (opts.path, _.bind (function (data) {
this.value = data;
}, этот) );
setInterval (_. bind (function () {
this.emit ("Event");
}, это), opts.freq || 100);
}
// Пример: jQuery.proxy
Функциональное устройство (Opts) {
this.value = null;
stream.read (opts.path, jquery.proxy (function (data) {
this.value = data;
}, этот) );
setInterval (jquery.proxy (function () {
this.emit ("Event");
}, это), opts.freq || 100);
}
// Пример: Dojo.hitch
Функциональное устройство (Opts) {
this.value = null;
stream.read (opts.path, dojo.hitch (this, function (data) {
this.value = data;
}));
setInterval (dojo.hitch (this, function () {
this.emit ("Event");
}), opts.freq || 100);
}
Предоставьте кандидата для создания псевдонима для этого, с самим собой как идентификатором. Это, вероятно, будет иметь ошибки, и его следует избегать как можно больше.
Кода -копия выглядит следующим образом:
// 6.B.3
Функциональное устройство (Opts) {
var self = это;
this.value = null;
stream.read (opts.path, function (data) {
self.value = data;
});
setInterval (function () {
self.emit ("Event");
}, opts.freq || 100);
}
C. Используйте эторг
Несколько методов прототипа в ES 5.1 имеют специальную встроенную метку ThisARG, используйте его как можно больше
Кода -копия выглядит следующим образом:
// 6.C.1
var obj;
obj = {f: "foo", b: "bar", q: "qux"};
Object.keys (obj) .foreach (function (key) {
// | Это | Теперь это `obj`
console.log (это [ключ]);
}, obj); // <- Последний параметр `thisarg`
// Распечатать...
// "foo"
// "бар"
// "qux"
Это может использоваться в Array.prototype.every, Array.prototype.foreach, Array.prototype.some, Array.prototype.map и Array.prototype.filter.
7. Разное
Идеи и идеи, которые объяснит эта часть, не догматичны. Вместо этого более рекомендуется быть любопытным в существующих практиках, чтобы попытаться обеспечить лучшее решение для выполнения общих задач программирования JavaScript.
A. Избегайте использования переключателя. Современное отслеживание метода будет функционировать черным списком с выражениями переключения.
Похоже, что и Firefox, и Chrome сделали значительные улучшения для переключения операторов. http://jsperf.com/switch-vs-object-literal-vs-module
Стоит отметить, что здесь можно увидеть улучшение: https://github.com/rwldrn/idiomatic.js/issues/13
Кода -копия выглядит следующим образом:
// 7.A.1.1
// Пример оператора переключения
Switch (foo) {
Случай "Альфа":
альфа();
перерыв;
Дело "бета":
бета();
перерыв;
по умолчанию:
// филиал по умолчанию
перерыв;
}
// 7.A.1.2
// Метод, который может поддерживать комбинацию и повторное использование, - это использование объекта для хранения «случаев».
// Используйте функцию для выполнения делегирования:
Формары VAR, делегатор;
// возвращаемое значение только для объяснения
случаи = {
alpha: function () {
// Заявление
// возвратное значение
вернуть ["alpha", arguments.length];
},
бета: function () {
// Заявление
// возвратное значение
return ["beta", Arguments.length];
},
_default: function () {
// Заявление
// возвратное значение
return ["default", arguments.length];
}
};
Delegator = function () {
var args, key, делегат;
// преобразовать `аргумент 'в массив
args = [] .slice.call (аргументы);
// Извлеките последнее значение из `аргумента
key = args.shift ();
// Вызовите филиал по умолчанию
Delegate = case._default;
// делегировать метод из объекта
if (case.hashownproperty (key)) {
Делегат = случаи [ключ];
}
// область ARG может быть установлена на определенное значение,
// В этом случае | null | в порядке
return delegate.apply (null, args);
};
// 7.A.1.3
// Используйте API в 7.A.1.2:
Делегатор («Альфа», 1, 2, 3, 4, 5);
// ["Альфа", 5]
// Конечно, значение ключа `case` может быть легко изменено на любое значение
var casekey, comeUserinput;
// Есть ли возможный ввод какой -либо формы?
SomeUserInput = 9;
if (comeUserInput> 10) {
casekey = "alpha";
} еще {
casekey = "beta";
}
// или...
casekey = comeUserInput> 10? «Альфа»: «Бета»;
// Затем...
Делегатор (Casekey, SomeUserinput);
// ["Бета", 1]
// Конечно, это можно сделать ...
делегатор ();
// ["по умолчанию", 0]
B. Возврат значения заранее для улучшения читаемости кода без большой разницы в производительности
Кода -копия выглядит следующим образом:
// 7.B.1.1
// не хорошо:
функция returnlate (foo) {
var ret;
if (foo) {
ret = "foo";
} еще {
ret = "Quux";
}
возврат возврата;
}
// хороший:
функция возвращается (foo) {
if (foo) {
вернуть "foo";
}
вернуть "Quux";
}
8. Нативные и хост -объекты (Примечание: я всегда думал, что объекты хоста не должны переводить, поэтому я переведу их в соответствии с общим методом написания)
Самый базовый принцип:
Не делайте ничего глупого, все всегда станет лучше.
Чтобы укрепить эту концепцию, пожалуйста, посмотрите эту демонстрацию:
«Все разрешено: нативное расширение» Эндрю Дюпон (JSConf2011, Портленд, Орегон)
http://blip.tv/jsconf/jsconf2011-andrew-dupont-everything-is-pertited-extending-buit-ins-5211542
9. Комментарии
Комментарии на одну строку размещены над кодом в качестве первого выбора
Несколько строк в порядке
Комментарии в конце строки следует избегать!
Метод JSDOC также хорош, но это занимает больше времени
10. Используйте только один язык
Независимо от того, на каком языке содействие программе (или команде) предусматривает, что программа используется, программа должна быть написана только на том же языке.
Приложение
Запятая первая
Все проекты, которые используют этот документ в качестве руководства по базовому стилю, не допускают форматов кода до общины, если только явно указан или не требуется автором.