Javascript-форум (https://javascript.ru/forum/)
-   Оффтопик (https://javascript.ru/forum/offtopic/)
-   -   JavaScript style guide, JSLint, Strict Warnings (https://javascript.ru/forum/offtopic/5633-javascript-style-guide-jslint-strict-warnings.html)

Octane 27.10.2009 22:54

JavaScript style guide, JSLint, Strict Warnings
 
Наверное, у всех есть какой-то свой собственный стиль написания кода. Некоторое время назад мне пришлось адаптироваться к принятому в проекте стилю, который сильно отличался от моего, первое время было очень неудобно, потом привык, но не очень нравилось. В итоге выработался следующий стиль кодирования:

FD:
function callee(arg) {
    // …
}

• между именем функции и открывающей скобочкой нет пробела
• открывающая фигурная скобка в той же строке
• закрывающая фигурная скобка на уровне function

FE:
var callee = function(arg) {
    // …
};

• между function и открывающей скобочкой нет пробела

Объект:
var obj = {
    property: value,
    method: function(arg) {
        // …
    }
};

• двоеточие не отделяется пробелом от имени свойства или метода

Ветвления:
if(…) {
    // …
}
else if(…) {
    // …
}
else {
    // …
}

• else/else-if yачинаются с новой строки
• пробела между if и открывающей скобочкой нет

Циклы:
while(…) {
    // …
}

do {
    // …
}
while(…);

for(…) {
    // …
}

• for только в качестве for-in

Конструкторы:
(new Date).getTime()

• скобки функции-конструктора не ставятся, когда возможно

Операторы:
typeof variable

if(!variable && "property" in object) {…}

var a = b ? c : d;

• минимум скобок
• разделяются пробелами, но не отбиваются пробелами от скобок

Переменные:
var a = 1, b = 2, c = 3;

var key, obj = {…};
for(key in obj) {…}

var a;
while(…) {
    a = i;
}


function(event) {
    event = event || window.event;
    var target = …;
}

• один var для нескольких переменных
• если до этого есть var, писать еще один внутри for ни к чему
• var не ставится внутри цикла (знаю, что интерпритированы они будут сразу)
• var не ставится, где попало, только в начале логических блоков
• существующие переменные не переопределяются с помощью var

Другое:
• все имена в camelStyle
• для отступов используется знак табуляции
• избавляемся от strict warnings в консоли Firefox
• не опускаем фигурные скобки
_____________________________

Только недавно догнал, что Firefox ругается только на такие функции:
function() {
    if(…) {
        return …;
    }
}

а не на все функции, которые ничего не возвращают :)


На некоторые вещи ругается JSLint, думаю, стоит ли следовать всем рекомендациям или это никому ненужные ограничения?

Ссылки:
MDC: JavaScript style guide
JSLint — The JavaScript Code Quality Tool

Вот, просто мысли в слух :)

Riim 27.10.2009 23:15

У меня так же, кроме:
Цитата:

else/else-if yачинаются с новой строки
Цитата:

пробела между if и открывающей скобочкой нет
Цитата:

скобки функции-конструктора не ставятся, когда возможно
Цитата:

var не ставится внутри цикла (знаю, что интерпритированы они буду сразу)
Цитата:

не опускаем фигурные скобки

И частично:
Цитата:

var не ставится, где попало, только в начале логических блоков
В циклах свободно использую.


Цитата:

for только в качестве for-in
тоже while люблю, но for иногда просто напрашивается.

Kolyaj 28.10.2009 08:48

У нас на первом курсе в первом семестре преподаватель не принимал плохо оформленные программы. Тогда все бесились, но щас я ему очень даже благодарен -- основные принципы в подкорке мозга зашиты. Собственно отличия, как правило, у всех только где ставить открывающую фигурную скобку, отступы табуляциями или пробелами, наименование переменных и еще может что по мелочи. Поэтому некоторые пункты удивляют.

Цитата:

Сообщение от Octane
• else/else-if yачинаются с новой строки

Так обычно делается, как раз, если открывающая скобка на новой строке.

Цитата:

Сообщение от Octane
• пробела между if и открывающей скобочкой нет

У if и вообще у всех операторов со скобками пробелы обычно ставятся.

Цитата:

Сообщение от Octane
• скобки функции-конструктора не ставятся, когда возможно

Вообще смысл непонятен. В результате в твоем примере скобки все равно есть, но хуже.

Цитата:

Сообщение от Octane
• разделяются пробелами, но не отбиваются пробелами от скобок

Унарные операторы тоже не видел никогда, чтобы пробелами отделялись. Минус унарный, я так понимаю, тоже с пробелом пишется?

Цитата:

Сообщение от Octane
• если до этого есть var, писать еще один внутри for ни к чему

На это я раньше внимания особо не обращал, но щас IDEA ругается, redeclare говорит.

Octane 28.10.2009 13:09

Цитата:

Сообщение от Kolyaj
Цитата:

Сообщение от Octane
• else/else-if начинаются с новой строки

Так обычно делается, как раз, если открывающая скобка на новой строке.

В MDC так рекомендуют :) и заключать в комментарии так удобнее.

Цитата:

Сообщение от Kolyaj
Цитата:

Сообщение от Octane
• пробела между if и открывающей скобочкой нет

У if и вообще у всех операторов со скобками пробелы обычно ставятся.

Вот тут не определюсь, после function в FE тоже тогда пробел нужно ставить будет по идее.

Цитата:

Сообщение от Kolyaj
Цитата:

Сообщение от Octane
• скобки функции-конструктора не ставятся, когда возможно

Вообще смысл непонятен. В результате в твоем примере скобки все равно есть, но хуже.

Вроде так нагляднее.

Цитата:

Сообщение от Kolyaj
Цитата:

Сообщение от Octane
• разделяются пробелами, но не отбиваются пробелами от скобок

Унарные операторы тоже не видел никогда, чтобы пробелами отделялись. Минус унарный, я так понимаю, тоже с пробелом пишется?

Не не не, это конечно же без пробелов:
i++;
++j;

a += -1 + k--;

Kolyaj 28.10.2009 13:19

Цитата:

Сообщение от Octane
и заключать в комментарии так удобнее.

С этим, пожалуй, соглашусь, хотя с нормальной IDE это неактуально.

Цитата:

Сообщение от Octane
Вот тут не определюсь, после function в FE тоже тогда пробел нужно ставить будет по идее.

У функций пробел перед скобкой не ставится, пробел перед именем относится к имени, нет имени -- нет пробела. Все логично :)

Цитата:

Сообщение от Octane
Вроде так нагляднее.

По сути, это в одном ряду с точками с запятой стоит, те тоже необязательны.

Цитата:

Сообщение от Octane
Не не не, это конечно же без пробелов:

В первом посте опечатка?

Octane 28.10.2009 13:51

Цитата:

Сообщение от Kolyaj
В первом посте опечатка?

ты про это:
! variable

?

Без пробела обычно пишу, поправил.

B~Vladi 28.10.2009 14:16

Мой стиль вы все прекрасно видели:)
Никаких пробелов, минимум переноса строк и скобок... Не завидую наследнику моего кода:D
Для таких ситуаций многие IDE имеют функцию форматирования. В DW для JS этого нет:(

Не понимаю людей, которые вставляют пробелы и переносы везде, где можно... Окно на весь экран, а смысла никакого не видно...

Dmitry A. Soshnikov 28.10.2009 14:16

Цитата:

Сообщение от Kolyaj
У функций пробел перед скобкой не ставится, пробел перед именем относится к имени, нет имени -- нет пробела. Все логично

А можно отнести имя к выражению вызова (CallExpression), тогда исчезает только имя, а пробел остаётся.

function foo() {...}  // описание функции с именем
foo(); // вызов

(function() {}); // без проблела - похоже на вызов
(function () {}); // а так - описание функции, исчезло только имя


Вот тут давно тоже было.

Что касается style-guide - это очень важная тема. Здесь приоритеты следующие (по убывающей, первые пункты - приоритет выше):

1. Style-guide принятый локально в компании. Главное - соблюдать единообразие кода.

2. Официальный Style-guide технологии. Профессиональный код (на международном уровне) должен выглядеть так. Автор технологии имеет право определять style-guide (в идеале, советуясь со сторонними мнениями и учитывая пожелания).

3. Локальная привычка. Любительский уровень, как правило используется новичками при начальном изучении. Также, может использоваться псевдо-гуру, которые хотят в этом моменте обособиться (aka, "мы не следуем за толпой и всякими там стайл-гайдами"), что является ещё большим пафосом; как правило - тоже любитель, знающий технологию ненамного глубже посредственного программера. Однако, первый пункт (с высшим приоритетом), может выбираться также конкретным человеком, исходя из своей локальной привычки и, если такой код сильно расходится с пунктом (2) - это неправильно уже.

Если не задан локальный стиль в компании, то стоит придерживаться официального стиля технологии - независимо от локальных привычек. Так, например, я привык к camelCase-у в именах переменных, но, программируя на Python-e, я использую underscore_case (т.к. это рекомендация официального style-guide-а Python) - несмотря на мою привычку из ES.

Octane 28.10.2009 15:29

А как лучше:
if(typeof addEventListener != "undefined") {…}

или
if(typeof window.addEventListener != "undefined") {…}

или
if(window.addEventListener) {…}

или
if("addEventListener" in window)  {…}

?

Dmitry A. Soshnikov, можешь объяснить, почему и как работает такая конструкция:
typeof X // "undefined"

когда переменная X нигде не определена? Нормально ли так делать?

Kolyaj 28.10.2009 15:36

Цитата:

Сообщение от Octane
А как лучше:

В таких (в конце файла), например, случаях без разницы, все равно работать не будет :)

Dmitry A. Soshnikov 28.10.2009 18:46

Цитата:

Сообщение от Octane
Dmitry A. Soshnikov, можешь объяснить, почему и как работает такая конструкция: typeof X // "undefined", когда переменная X нигде не определена? Нормально ли так делать?

Нормально, это связано с грамматикой языка.

typeof (11.4.3, ES-3) - это рекурсивное UnaryExpression.

UnaryExpression :
  [...]
  typeof UnaryExpression
  [...]


Т.е. можно написать так:

alert(typeof typeof []); // string


Также, UnaryExpression в одном из нетерминалов распадается на PostfixExpression:

UnaryExpression : 
  PostfixExpression
  [...]


Далее, нетерминал PostfixExpression может содержать LeftHandSideExpression:

PostfixExpression :
  LeftHandSideExpression
  [...]


который, в свою очередь одним из нетерминалов имеет CallExpression.

LeftHandSideExpression :
  [...]
  CallExpression


CallExpression имеет у себя MemberExpression.

CallExpression :
  MemberExpression Arguments
  [...]


MemberExpression может содержать PrimaryExpression:

MemberExpression :
  PrimaryExpression
  [...]


А уже PrimaryExpression (наконец-то ;)) одним из своих нетерминалов имеет Identifier:

PrimaryExpression :
  [...]
  Identifier
  [...]


А дальше, работает обычное разрешение идентификаторов в Scope chain (10.1.4). И в этом случае будет возвращён объект типа Reference с базой null и именем свойства - "X". Главное здесь - база null, поскольку далее отрабатывает пункт (3) алгоритма typeof:

3. If GetBase(Result(1)) is null, return "undefined".

Цитата:

Сообщение от Octane
if(typeof addEventListener != "undefined") {…}

Цитата:

Сообщение от Octane
if(typeof window.addEventListener != "undefined") {…}

В обоих случаях работает разрешение имени идентификатора. Во втором случае ищется имя "window" и дальше вызывается [[Get]] по имени свойства "addEventListener", во первом случае ищется имя "addEventListener" без дополнительных доступов к свойствам.

Цитата:

Сообщение от Octane
if(window.addEventListener) {…}

Просто анализируется цепь прототипов на получение значения свойства. Если свойства нет, вернётся undefined.

Цитата:

Сообщение от Octane
if("addEventListener" in window) {…}

Анализируется цепь прототипов на наличие свойства. Данный случай предостерегает, если значение свойства будет false (проверка предыдущего примера не отработала бы).

Цитата:

Сообщение от Octane
А как лучше:

Логика работы известна - выбирай ;)

Octane 28.10.2009 19:54

Спасибо :)

alexKniaz 28.10.2009 21:32

Цитата:

Сообщение от B~Vladi (Сообщение 33739)
Мой стиль вы все прекрасно видели:)
Никаких пробелов, минимум переноса строк и скобок... Не завидую наследнику моего кода:D
Для таких ситуаций многие IDE имеют функцию форматирования. В DW для JS этого нет:(

Не понимаю людей, которые вставляют пробелы и переносы везде, где можно... Окно на весь экран, а смысла никакого не видно...

Читать большой код может быть неудобно.

Octane 01.11.2009 18:38

Начитался блин всяких style guide'ов и черновиков ECMAScript 5 :-E надо же всегда помнить про IE!

По новому стандарту ссылка arguments.callee не будет работать в "strict mode"; Решил попонтоваться и избавится он нее заранее следующим образом:
(function callee() {

    …

    if (…) {
        setTimeout(callee, …);
    }

}());
Но у нас же есть JScript, в котором такая функция будет видна и в текущем контексте исполнения:
(function callee() {});
alert(callee);


Цитата:

Сообщение от MDC JavaScript style quide
• Name inline functions, this makes it easier to debug them. Just assigning a function to a property doesn't name the function, you should to do this:
var offlineObserver = {
  observe: function OO_observe(aSubject, aTopic, aState) {
    if (aTopic == "network:offline-status-changed")
      setOfflineUI(aState == "offline");
  }
};

Ага, удобно значит дебажить, свойство name функции будет не пустой строкой, но в JScript этот OO_observe вывалится в глобальное пространство.

Вот и улучшили код)

Dmitry A. Soshnikov 01.11.2009 19:11

Цитата:

Сообщение от Octane
в JScript этот OO_observe вывалится в глобальное пространство.

Это ещё что! ;) Дальше - больше, JScript создаёт два объекта в этом случае:

var referenceToNFE = function testNFE() {
  alert('testNFE');
};
 
alert(referenceToNFE === testNFE); // false
 
referenceToNFE.newProperty = 10;
alert(testNFE.newProperty); // undefined
 
// однако, два объекта выполняют
// одинаковые действия
testNFE(); // "testNFE"
referenceToNFE(); // "testNFE"


Подробней.

Kolyaj 01.11.2009 21:25

А вот чем им, собственно, arguments.callee не угодил?

alexKniaz 12.11.2009 18:37

А чем им модель w3c не угодила Вот-вот. Её ведь в конце концов можно расширить и не превратив в модель Microsoft-а

subzey 29.11.2009 23:26

Цитата:

Сообщение от Kolyaj (Сообщение 34149)
А вот чем им, собственно, arguments.callee не угодил?

Присоединяюсь к вопросу. Кому, собственно, мешает arguments.callee?

GuardCat 04.10.2011 10:02

Назовёте некропостером... Но спрошу: почему в javascript используется чаще всего «египетский» стиль расставления фигурных скобок? Мне кажется читаемее (ну и слово) то есть читабельнее(ещё хуже) было бы как в Java/C/C++?

И если я пишу вот эдак:
function print(txt)
{
	document.write(txt,"<br>");
}
Это приемлемо?

Египетская сила =)

B~Vladi 04.10.2011 10:13

try
{
// Code
}
catch (e)
{
// Code
}

Так тоже читабельнее? Или так:
do
{
// Code
}
while ();


Имхо, код разрастается неоправдано.

GuardCat 04.10.2011 10:26

Хе-хе, тогда уж
t
r
y
{
}
c
a
t
c
h
(
e
)
{
}

Я делаю так:
try
{
	//code
} catch(e) {
	//code
}

do
{
	//code
} while();

if ()
{
	//code
} else {
	//code
}

И сейчас меня побьют за } else { и } catch { =)

Да, код растёт по вертикали. Но визуально удобнее ловить скобки, особенно если без подсветки синтаксиса работаешь. Кстати, год почти, приходилось писать скрипты на Symbian 9. И писал на небольшом экране (E63). Показалось так удобнее.

Одним словом, верно ли я понимаю, что нет принятого стандарта?

B~Vladi 04.10.2011 10:32

Цитата:

Сообщение от GuardCat
верно ли я понимаю, что нет принятого стандарта?

Верно, но общий стиль уловить можно и он не всегда сходится с твоим.
Цитата:

Сообщение от GuardCat
И сейчас меня побьют за } else { и } catch { =)

Вот именно :)

Вообще форматирование кода не так страшно, ибо во всех продвинутых IDE можно быстро отформатировать под себя. Но в этом случае растет Diff, так что в команде лучше писать в одном стиле.

Цитата:

Сообщение от GuardCat
особенно если без подсветки синтаксиса работаешь

Жесть. Хотя у нас тут один в блокноте пишет и не обламывается.

Я вот не могу читать такой код :)

Kolyaj 04.10.2011 10:36

Цитата:

Сообщение от GuardCat
И сейчас меня побьют за } else { и } catch { =)

Конечно побьют, надо быть последовательным.

Цитата:

Сообщение от GuardCat
Но визуально удобнее ловить скобки, особенно если без подсветки синтаксиса работаешь.

А чего их ловить? Отступов достаточно.

B@rmaley.e><e 04.10.2011 10:49

Цитата:

Сообщение от GuardCat
Мне кажется читаемее (ну и слово) то есть читабельнее(ещё хуже) было бы как в Java/C/C++

А как в Java/C/C++? Я спокойно использую там египетские скобки и божественная кара не настигла меня.
Цитата:

Сообщение от GuardCat
Но спрошу: почему в javascript используется чаще всего «египетский» стиль расставления фигурных скобок?

function fnc()
{
  return 
  {
    a : 5,
    b : 'string'
  }
}

alert( JSON.stringify(fnc()) ); // и чего бы Вы ожидали?

GuardCat 04.10.2011 11:06

Отличный пример! Точка с запятой втыкается после return на автомате! А ведь и правда, мог бы так написать.
Да, косяк. Похоже, необходимо переквалифицироваться в египтяне =)

Цитата:

Сообщение от B@rmaley.e><e
А как в Java/C/C++? Я спокойно использую там египетские скобки и божественная кара не настигла меня.

О богохульник, она настигнет тебя рано или поздно! :)

Кстати, в C# майкрософтовская визуальная среда насильно лишает листинг египетской сущности. Я сделал вывод, что египет — это неверно для любого языка. Преждевременный вывод.

:dance:

Ититская сила! А в Java-то египетские скобки — стандарт! http://www.oracle.com/technetwork/ja...oc-136057.html

melky 04.10.2011 11:14

у меня в общих чертах схоже, но :

ставлю пробелы-границы между скобочками и тем, что туда попадает
// т.е. не,
if(condition){
.....
}

// ,а
if( condition ){
   .....
}


и так же с аргументами.

function a( a,b,c ){}

a( a,b,c );

ещё для наглядности могу не ставить запятые между аргументами, если имена переменных небольшие. иначе - ставлю

a( a,b,c );
a( very_longggg, oh_yeaaah );

Kolyaj 04.10.2011 11:17

Я никогда не понимал пробелов внутри скобок. Снаружи надо отбивать, а не изнутри.
if (condition) {

}

melky 04.10.2011 11:29

когда есть скобки внутри condition (вызов функции проверки, z.b.), то можно запутаться, если проглядывать код, а не вчитываться.

вкусы ?

Kolyaj 04.10.2011 11:55

Цитата:

Сообщение от melky
вкусы ?

Нет, общепринятые нормы. Никто не ставит пробела перед знаком ? в текстах. Никто не не пришет( скобки )так, все (так) пишут.

melky 04.10.2011 12:01

что же, придётся переучиваться для этого? нормы есть нормы, для их соблюдения.

B@rmaley.e><e 04.10.2011 20:00

Цитата:

Сообщение от melky
придётся переучиваться для этого?

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

monolithed 05.10.2011 08:40

Цитата:

Сообщение от GuardCat
Мне кажется читаемее (ну и слово) то есть читабельнее(ещё хуже) было бы как в Java/C/C++

Какой использовать Indent style - личное дело каждого, если это не регламентировано. Если брать императивную парадигму, то лично мне больше импонирутK&R style.
Цитата:

Сообщение от Kolyaj
Я никогда не понимал пробелов внутри скобок. Снаружи надо отбивать, а не изнутри.

их расставляют многие IDE (к примеру VS) и JSLinter's

B~Vladi 05.10.2011 09:02

Цитата:

Сообщение от monolithed
личное дело каждого

Ну я бы так не сказал. Касаемо пробелов в скобках уже сказали:
Цитата:

Сообщение от Kolyaj
Никто не не пришет( скобки )так, все (так) пишут.

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

tenshi 05.10.2011 09:38

в письменной (речи (не (употребляются (вложенные (скобки))))

Андрей Параничев 14.10.2011 18:11

var someVariable  = "someValue",
    someVariable2 = "someValue",
    someVariable3 = "someValue";

или
var someVariable  = "someValue"
  , someVariable2 = "someValue"
  , someVariable3 = "someValue";


И еще
if (a) b(); // Но:
if(!a) {
    a = 5;
}

Как считаете, это неправильно?

x-yuri 15.10.2011 00:26

в принципе можно операторы в начало строки выносить, &&, || в этом случае легче найти, запятые... сложнее забыть указать. По поводу фигурных скобок - их лучше всегда указывать, так проще добавлять отладочные операторы. Отличие в пробелах, непонятно зачем, лучше придерживаться более распространенного варианта. Разве что можно ! отделять пробелами:
if ( ! a) {...}


Часовой пояс GMT +3, время: 02:34.