Pull to refresh

Comments 84

На практике надо ставить везде, ибо все так или иначе сжимают скрипты. И отсутствие точки с запятой может вызвать ошибку в сжатом скрипте, которую крайне сложно найти.
При обфускации убираются лишние символы? Или лучше делать вручную?
YUI оптимизирует/сжиает названия переменных, методов, которые не достаются из замыкания/функции.
Популярный пример:
var a = function () {}
a.prototype.b = 100;
alert((new a()).b);

В первой строчке можно и не ставить ";" все работает.
Сжимаем это дело YUI, получаем фактически неисправимую ошибку (SyntaxError: missing; before statement on line 1):
var a=function(){}a.prototype.b=100;alert((new a()).b);

Этот код маленький, и вы легко найдете и исправите ошибку. На практике это сделать невозможно: «SyntaxError: missing; before statement on line 1», а вся строка длинной 50Кб где начнем искать? :)
Поэтому перед сжатием я советую обработать скрипт JSLint'ом
Ваш пример после применения yuicompressor был преобразован в абсолютно корректный код:
var a=function(){};a.prototype.b=100;alert((new a()).b);


Я никогда не ставил ";" после "}" и никогда не было проблем с YUI. Так что это Вы зря. Тем не менее, JSLint лишним не будет.
И правда, недавно начал использовать YUI не знал, что он такой умный (код в примере сжал руками). JsMin, например, портил код.
Протестировал другой проблемный код:
if (window)
window.a = 100;
else 
a = 100;
b = 100
на выходе все верно
if(window){window.a=100}else{a=100}b=100;

Чтож, респект Yahoo! за YUI
UFO landed and left these words here
поэтому стоит отказаться от этой кривой поделки и воспользоваться gcc, а не добавлять костыль в виде линта.
Легче всего следить так: пишешь один оператор на строку, ставишь после него точку с запятой (кроме каких-нибудь исключений). Если хочется сжать скрипт по размеру — в конце убираешь все переносы строк, а ТЗ при этом будут расставлены верно.
Легче всего писать код так, чтобы потом не было больно его читать и поддерживать =)
А если хочется сжать, то наверно лучше использовать компрессор. Он и названия переменных минимизурет и ненужные скобки поубирает, а может и function inlining сделает если это уменьшит размер кода.

Кстати, jQuery с относительно недавних пор использует Google Closure Compiler вместо YUI compressor.
Но у YUI комрессора есть одно преимущество — он и CSS сжимает заодно, не надо отдельный компрессор держать для CSS.
А что это за мода такая пошла переносить запятую в начало следующей строки при перечислении, например, имен переменных? Очень неприятно такой код читать (как отступы перед знаками препинания, получается).
Это чтобы случайно не поставить запятую после последнего элемента.
Мне тоже кажется, что тут решение проблемы хуже, чем сама проблема.
Это вроде как такой кодстайл в серверном JS используется. Во многих модулях для Node.js такое видел.
В самом node.js код написан без этих выкрутасов.

Единого стиля кода, с которым согласны все в js, все равно нет. Отступы — то табы, то 4 пробела, то 2 пробела; точка с запятой — то ставится, то не ставится; запятая — то в начале строк, то в конце, и т.д. Хорошо хоть с camelCase определились.
Единого стиля нет ни в одном языке. jslint.com + [The Good Parts Mode] хороший тон, дня JavaScript
pep-8?
в питоне сразу заклюют, если не по pep-8 код. Поэтому все пишут по pep-8 и проблем не имеют. Не так ведь важно, какие именно соглашения, главное — чтобы они соблюдались, а в js этого нет.
Кто это все? Угу, даже стандартная библиотека не придерживается например такого из pep-8:

Limit all lines to a maximum of 79 characters.

Там вступление есть о том, как pep-08 применять (A Foolish Consistency is the Hobgoblin of Little Minds).
Нене, добавить новый элемент проще (запятая + элемент в 1 строчку). Кодогенераторам проще.
как вы ласково отозвались о программистах, употребляющих этот стиль)

Странно, что этот стиль вообще употребляют в серверном js. V8 завершающую запятую игнорирует, вот это работает (только что проверил):
var arr = [
   'vasia',
   'petya',
];

Может, чего-то я тут не понимаю, но это уж получше читается.
Бегом показывать этот массив IE =)
Снимаю шляпу. Работает =(
в IE6 и IE7 не работает.

Но этот синтаксис (запятая после последнего элемента) не запрещен в ECMAScript 3 и явно разрешен в ECMAScript 5.

Мне кажется, что такие странные приемы для обхода багов IE на сервере под V8 смотрятся диковато и бессмысленно.
В случае расшаренного кода, который испольуется и в браузезе и на сервере, смысл есть.
Поставить IE на linux-сервер без иксов и запустить его как интерпретатор js из программы на node — задача, прямо скажем, нетривиальная.
Всё работает. Попутал я с хеш массивом, где запятая критична.
длину массива сравните в ие и в других браузерах, вроде бы в ие должно быть побольше…
Работает, но добавляет лишний null-элемент в конце массива.
Что еще хуже ибо может совершенно неожиданно вылезти боком.
Не работало бы, если бы это был литерал объекта.
Проверил сейчас на node/V8, длина массива не меняется от добавления запятой, и при создании объекта ( var dict = {'foo': '1', 'bar': '2',}) никаких ошибок не вываливается, объект создается правильно. Вы точно не поведение IE описываете?
Я точно поведение IE описываю :-D
Про специфику V8 вообще не очень в курсе.
Написал камент об этом ниже, не прочитав сначала ваш.
Так вот, по-моему такое поведение логично.
по-моему, такая конструкция должна работать и быть эквивалентна
var arr = [
   'vasia',
   'petya',
   null
];

var a = [ «a», «b», ];
a.length // 2

var a = [ «a», «b», null ];
a.length // 3
Сразу видно, что строка не является самостоятельной. И операторы "+", "-" тоже лучше писать с новой стороки, что бы четко видеть, что это просто продолжение предыдущей строки.
Мне думается, несамостоятельность строки можно указать отступом.
А вот с операторами — это не для javascript совет. Пример:
function f() {
//…
return
-42;
}

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

ЗЫЖ ну а что неприятно… — это дело привычки.
Вы наверно ещё не видели такое:
var a = 1
   ,b = 2
   ,c = 3
   ,d = 4
   ;
Ага, это я и имел в виду. Встретил подобное в исходном коде фреймворка express для node.js. Ранее автор грешил как раз опусканием точки с запятой везде, где только можно, сейчас отказался от затеи. Надеюсь, и эта мода пройдет.
Не привычно, но следует сказать спасибо TJ Holowaychuk за express пусть и с таким кодом, похожим на гребенку. Я рад, что он уходит от плохого.
Ещё очень часть переносят на новую строку метод в цепочках вызовов. И опять же ставят точку с запятой в конец, чтобы было удобнее добавлять новый вызов в цепочку. С этим подходом я полностью согласен.
$('#button')
.css('color', 'red')
.click(onbuttonClick)
.animate({width: '150px'})
;
Как по мне — слишком много буков.

Проще, надежнее и понятнее ставить; всегда по окончании оператора, как в C/С++/С#, Java. Автовставка от лукавого.
Статья призывает преодолеть ложное чувство простоты, надёжности и понятности в случаях типа
return
   (a + b);


ибо здесь точка с запятой лишь создаст впечатление, что всё правильно.
Как сторонник правила «явное лучше неявного», считю, что точку с запятой надо ставить всегда. К чему лишние трудности в чтении и понимании?
В случае с точкой с запятой — согласен полностью. А вот насчет правила «явное лучше неявного» — не всегда. Зависит от того, насколько однозначно можно трактовать «неявное» исходя из контекста. Если однозначно — лучше пусть будет неявно. Это касается всех случаев использования «Conventions», тех самых, которые «over Configuration».
категорически согласен.
Я привык писать на JS так же как на C++, поэтому о некоторых тонкостях не знал, если честно, но и не встречал на практике. Хотя статья интересная, но уж больно длинная…
Присоединяясь к двум предыдущим комментаторам добавлю что линтеры (jslint, google linter) помогут не забыть это делать всегда.
jslint в свое время заставил изучить эту тему
UFO landed and left these words here
Если разрабатываешь на каком-нить языке программирования (к примеру PHP) то проще следовать основному языку, т.к. так привычней и глаз не режет отличия в окончании строк.
Согласен. У меня основной руби, и поэтому мне режут глаз точки с запятой. Что же касается компрессоров, то статья высказывается в том смысле, что компрессоры, которые не могут осилить валидный код, хоть и без ТЗ, нужно выкинуть. Ибо неизвестно, где ещё они накосячат.
Лишняя точка с запятой и все фигурные скобки — хороший тон для JavaScript. Я представляю как не ловко программистам Python видеть такое
var a = {
   b: function () {
       if () {

       }
   }
}
Их наверно одна конструкция function (){if(){}} сводит с ума :) Все современные компрессоры заставляют программистов писать хороший JavaScript код: ставить везде; и везде использовать {}. Так что не нужно винить компрессоры они делают хорошую работу. Я понимаю вашу привычку, но и вы уважайте этот дополнительный язык, его программистов, которые возможно будут читать ваш код и его тон хороших скриптов.
Эээ… а при чём тут питон? Я очень уважаю js, и не считаю его дополнительным, и кода пишу не меньше, чем на руби. Вышеприведённый фрагмент не содержит ни одной точки с запятой, и никак не противоречит моим принципам, и ничего дикого я не вижу. Ну разве что не скомплируется с пустым условием =)

Нет никакой разницы, говорим ли мы «точка с запятой необязательна, почти всегда парсер её вставит», как в js, или же «точка с запятой не нужна, но в редких случаях нужно '\' для продолжения строк», как в руби, это всего лишь дело устоявшихся традиций, основанных, не в последнюю очередь, на неинформированности.

Если я пишу для себя, я ТЗ не ставлю, наряду с другими своими правилами оформления кода, и мне все равно, кто что про это думает, никакого неуважения ни к кому я не выказываю, и не считаю что хороший тон это «точки с запятой всегда». Вероятность того, что мой код будет читать кто-то, отличный от меня, довольно низка, а того, что кто-то неотличный, напротив того, очень высока, так что приоритеты соответствующие.
Программисты Python ненавидят лишние скобки (в Ruby, на сколько я знаю, тоже не одобряют стиль со скобками), поэтому и привел такой пример. И поэтому зачастую норовят написать вот так if(a) a=100 else b=200, что очень напрягает меня и многих JavaScript программистов. Многие вешают на JavaScript тег «Дополнительный язык» — могу писать как хочу. У вас хороший подход к языкам, комментарий полностью разъяснил мне вашу позицию.
Программисты на Python не только не любят лишние скобки, но и лишние уровни вложенности.
«Плоское лучше, чем вложенное»

def test(a):
>>if type(a)!=str:
>>>>return False
>>if a[0]=='0':
>>>>return False
>>return a[::-1]

и

def test(a):
>>if type(a)==str:
>>>>if a[0]!='0':
>>>>>>return a[::-1]
>>return False

В первом случае код длиннее, но зато основная работа функции на виду. то есть, в начале мы явно указали, в каких случаях функция не работает с объектом, а потом без лишней вложенности описали, что делается, если объект нам подходит. Во втором же случае основная работа с объектом на два уровня глубже, что делает код трудночитаемым.
без лишней вложенности. короче и понятнее вот такой вариант
def test( a ):
    if type( a ) != str or a[ 0 ] == '0' :
        return False
    return a[::-1]

и если появятся еще «исключительные условия», то их стоит добавить в первое условие.
читабельность от этого не пострадает. в крайнем случае если условия очень запутанные и хитрые, то разбить их на несколько строк, примерно вот так:
def test( a ):
    if a is None \
        or type( a ) != str \
        or a[ 0 ] == '0' :
        return False
    return a[::-1]
Надо бы точку с запятой в конце поставить… после последней фигурной… для порядку. ;-)
Глупости. Если разрабатываешь на каком-нить языке программирования (к примеру PHP) не надо тащить его в другой язык программирования. Следует понимать, что ты делаешь или отдать тому, кто понимает.
А при чем тут тащить язык? Я вполне понимаю и PHP и JavaScript, но мне привычней ставить ТЗ, вот и все…
Вот прочитал же, что ТЗ тут «точка с запятой». А при чтении упорно всплывает «Техническое Задание». Не плодите сущностей…
Поддерживаю. В исходном тексте никаких сокращений нет, а переводчик ввел новую аббревиатуру, которая к тому же имеет в нашем языке устойчивое значение. Следовало использовать конструкцию «;» или писать полностью.
И ведь ещё и приживётся этакий новый смысл, чего доброго.

(Кстати, на «ТСЗ» также нельзя исправить это, потому что «ТСЗ» является общепринятым сокращением словосочетания «товарищество собственников жилья».)
Можно «тчк зпт» или без пробела «тчкзпт», в телеграфном стиле пишут так:

ИЗ ЧИСЛА ЛАУРЕАТОВ СООТВЕТСТВУЮЩИХ ПРЕМИЙ ПРАВО НА ДОПОЛНИТЕЛЬНОЕ МАТЕРИАЛЬНОЕ ОБЕСПЕЧЕНИЕ ИМЕЮТ двтч
ЛАУРЕАТЫ СТАЛИНСКОЙ ПРЕМИИ тчк зпт
ЛАУРЕАТЫ ЛЕНИНСКОЙ ПРЕМИИ тчк зпт
спасибо, очень хорошая статья — всё по делу
за
i
++
j

и д.р. выкрутасы надо по рукам бить
Вот если был бы JavaScript трибунал, то бы за ваш всего лишь посадили в карцер
А вот, думаю, за такой минимальное наказание — расстрел на месте:
b=(a=[0,1,2][0,1,2])?
!!~~++a+1..toString
(void(a))
:(c=eval)
('alert("42")');

Да, и это код прекрасно работает. Кто-нибудь скажет сходу, что будет в b? :)
console.log(b); ( и да — с ТЗ в конце :) ) спасёт отца русской демократии на просторах Яваскриптовых поделок
такс. ну a будет равно [0,1,2][2], следовательно 2, следовательно правый код тернарного оператора (alert("42")) не выполнится. разбираем левую часть. в toString аргументы никакие не передаются, потому void(a) это просто шум. ~~ равносильно parseInt. 1. равносильно 1.0 или (1).
Следовательно, принимаем одно из следующих выражений:
!!(parseInt(++a + 1).toString());
(!!parseInt(++a)) + ((1).toString());
!!(parseInt(++a) + ((1).toString()));
!!parseInt(++a + (1).toString());

Я в порядке выполнения этих операндов плаваю, на самом деле, потому всегда стараюсь ставить скобочки(

Все, кроме второго выражения возвращают true, второе — «true1». Правильный ответ «true1», но это я уже посмотрел в файрбаге:

(!!parseInt(++a)) + ((1).toString());


Хотя я не верю в реальность такого кода )
~~ не равносильно parseInt, а так всё правильно.
ну да, ~~'08' и parseInt('08') вернут разный результат, но в данном случае они равносильны
В данном случае ~~ вообще бессмысленнен, но самое главное, что
parseInt("12px") → 12
~~"12px" → NaN

var o = {toString: function(){return "5";}, valueOf: function(){return 3;}};
parseInt(o) → 5
~~o → 3

Я просто придираюсь к словам. Уверен, что вы понимаете разницу, но не нужно смущать тех, что не понимает.
>Всё, что надо знать о точке с запятой
>СТЕНА ТЕКСТА
>СТЕНА ТЕКСТА
>СТЕНА ТЕКСТА
>СТЕНА ТЕКСТА
>СТЕНА ТЕКСТА
>Перевод
мда. им там на западе писать то больше не о чем?
вижу статью активно плюсуют. за что? по-моему у большинства хабраюзеров уже рефлекс — СТЕНА ТЕКСТА, значит надо плюсануть.
давайте запостим вывод компиляции ядра линукса. ну, вывод make.
там будет стена текста раз в 20 а то и 50 больше, значит получим 100-200 плюсиков.
только не забыть вставить красивую картинку с с*ськами до ката.
Как заметил у них там на западе бывший президент Франции Миттеран, вы только что «упустили великолепную возможность промолчать» ;)
правильный у вас юзерпик
ТСЗ не обятательна в конце файла, да, но на практике это приводит к очень сложноловимой ошибке, когда все файлы конкатенируются вместею получается
Получается
1.js
var one = {}
2.js
var two = 1
А после конкатенации
var one = {}var two = 1
Если конкатенация проводиться только на production сервере — то такую ошибку очень тяжело ловить.
Поэтому зачастую у опытных программистов можно встретить ТСЗ первым символом в файле — так они защищаются от подобных ситуаций, потому что зачастую не знаешь что за файл будет перед твоим при конкатенации.
Конкатенировать файлы через пробел — допускать нарушение спецификации ECMAScript. Явно сказано, что перед концом файла парсером автовставляется точка с запятой.

Ну и кроме того, «хороший тон» иметь в конце файла всё же CR.
Поскольку для конкатенации нет стандартных решений — то каждый реализовывает по-своему. Соответственно не зная написанного выше можно напороться на очень нетривиальный и сложноловимый баг.

Я тут проводил раскопки и обнаружил странный артефакт:


a = b + c
;(d + e).print()

Не надо так писать, в JS есть специально предназначенный для этого оператор:


a = b + c
void (d + e).print()
Only those users with full accounts are able to leave comments. Log in, please.