Повышение качества javascript кода. JSLint


    Случилось так, что в последнее время мне пришлось читать и рефакторить очень много ужасного javascript-кода. Работа с таким кодом стоит очень многих нервов при сопровождении, да и писать/отлаживать такой код не приятно. Мысли о том, что заставляет людей писать плохой код и как с этим можно бороться заставили меня писать эту статью. Не претендую на сколь-нибудь полное раскрытие темы борьбы за качество кода, хочу рассмотреть лишь некоторые аспекты, доставляющие наибольшее количество проблем. В качестве основного инструмента оптимизации качества кода предлагаю использовать JSLint, который несмотря на все плюсы, не является панацеей и может служить лишь отправной точкой для дальнейшего улучшения кода.

    Всех у кого хоть раз болела голова при написании/чтении javascript кода прошу под кат.

    Стандарт на службе у человека или наоборот?



    JavaScript расхолаживает. Этот язык спроектирован так, чтобы быть максимально простым и ненавязчивым, чтобы человек не знающих многих премудростей, мог легко начать писать на javascript и решать при этом реальные задачи. Обилие javascript-фреймворков, о которых разговор пойдет позднее, только ухудшает ситуацию. Итак, javascript — язык грязный, допускающий вольности со стороны разработчика. Таким образом, если просто писать как получается, то написать множно сколь угодно плохо — язык не запрещает. Естественно, для сложных проектов такой подход недопустим.

    Чтобы сделать язык строже, существуют стандарты кодирования. В своей практике я получаю наибольшую отдачу, используя инструмент валидации кода — JSLint. Если пройти по ссылке, можно прочитать предупреждение автора, Дугласа Крокфорда, о том что JSLint will hurt your feelings. И это действительно так — меня очень сильно задело, когда валидатор нашел полсотни ошибок в 50 строках работающего кода. Поначалу казалось дикостью, что всем этим ненужным условностям надо следовать, что надо ломать пальцы переучиваясть ставить пробелы и ненужные скобки. Писать вместо
    if(element.parentNode&&Math.max(offset1,offset2,offset3)>x1){
    	arr = new Array();
    	for(var i in some_object){
    		if (i == qwerty) continue;
    		arr.push(i);
    		
    	}
    }

    как-то так:
    /*global qwerty: true, some_object: false */
    if (element.parentNode && Math.max(offset1, offset2, offset3) > x1) {
    	var arr = [], i;
    	for (i in some_object) {
    		if (some_object.hasOwnProperty(i)) {
    			if (i === qwerty) {
    				continue;
    			}
    			arr.push(i);
    		}
    	}
    }


    Потом на глаза попалась библиотека jQuery, где весь исходный код валиден (ну почти), а также много другого хорошего и умного кода. Я решил следовать этому стандарту в качестве эксперимента. В результате получил сильно возросшее качество создаваемого кода, которое выражается в меньшем количестве ошибок при отладке, лучшей читабельности, очевидности кода. При чтении кода сразу видны становятся проблемные места, ошибки в проектировании, потенциальные уязвимости и неоднозначности. Также есть полезный побочный эффект использования JSLint — в ответ на предупреждение валидатора приходится иногда задумываться в таких местах на которые просто не обращаешь внимания обычно, как правило это приводит к исправлению ошибки до её фактического проявления, то есть облегчает отладку, а иногда и помогает улучшить архитектуру разрабатываемого приложения. В общем, мир программирования стал бы гораздо чище и лучше, если бы валидация кода с помощью JSLint стала обычной практикой при разработке.

    JSLint. Основные требования к коду



    Привожу далее вольную интерпретацию текста Дугласа Крокфорда касательно ограничений, накладываемых на javascript. Лучше читать, оригинал, конечно.

    Глобальные и локальные переменные



    Глобальные переменные по праву можно назвать величайшим злом не только в javascript, но и во всех языках программирования. Думаю, не надо объяснять, почему (если надо то вот). В javascript глобальные переменные можно объявить в локальном контексте, что только усугубляет ситуацию, потому что иногда можно объявить глобальную переменную по ошибке, просто поторопившись, и, если повезет с названием переменной, то разработчик который будет сопровождать ваш код сойдет с ума, пытаясь понять смысл, который попытался вложить в глобальную переменную автор.

    Ничего такого не произошло бы, если бы использовался JSLint, который запрещает объявлять переменные без использования ключевого слова var. А если переменная действительно глобальная, JSLint заставит вас указать это явно, посредством комментария /*global variablename */, причем конкретизируя, допускается ли в данном контексте присвоение переменной значения.

    В строгом режиме JSLint приучает нас использовать var не более одного раза для каждого локального пространства имен. Это конечно перегиб, но я бы лучше воспринял это как призыв к рефакторингу — ведь переменную лучше всего объявлять непосредственно перед использованием, а значит группы объявлений должны быть разбросаны по методу, локализуя места использований, таким образом, локальные области большого метода лучше будет оформить как новые функции с названиями, определяющими суть действия, задокументировав таким образом код, не используя комментарий, одновременно улучшив валидность по JSLint.

    Точка с запятой



    Больной вопрос для многих программистов, в особенности Ruby — не любят точки с запятой ставить и всё тут. При написании кода на javascript надо зарубить на носу раз и навсегда — точки с запятой ставятся после каждой инструкции. Исключения: for, function, if, switch, try и while. Обратите внимание, что не надо ставить точку с запятой при объявлении функции:
    function f(x) {
    
    }

    однако, необходимо ставить ее при присвоении переменной значения:
    var f = function (x) {
    
    };


    Перенос длинной строки



    Строка более 80 символов — плохо. Забудьте про widescreen-мониторы, дело не в скроллинге, строка кода должна охватываться одним взглядом. Но и строки разбивать надо особо — чтобы после в месте разрыва строки явно отслеживалась синтаксическая незавершенность. JSLint допускает разрыв строки только после следующих операторов:
    , . ; : { } ( [ = < > ? ! + - * / % ~ ^ | &
    == != <= >= += -= *= /= %= ^= |= &= << >> || &&
    === !== <<= >>= >>> >>>=

    JSLint запрещает перевод длинной инструкции после строки, числа, идентификатора, закрывающей скобки или суффикс-операторов: ) ] ++ —

    Локальные пространства имен



    В javascript локальное пространство имен порождает только одна инструкция — функция. Ни for, ни while, ни if не порождают локальных пространств имен. То есть, в следующем примере:
    if (x === y) {
        var z = 1;
    }
    alert(z); // 1

    Переменная определенная внутри блока if доступна и вне блока, в то время как
    (function () {
        var x = 1;
    })();
    alert(x); // error (undefined variable x);

    переменная объявленная в функции не будет доступна вне ее, однако, если переменная объявлена вне функции, а функция объявляется в одном контексте с переменной, то переменная будет также видна в функции, другими словами:
    var x = 1;
    function f() {
    	alert(x);
    }
    f(); // 1


    Касательно понимания механизмов работы замыканий обычно возникают трудности в примерах типа такого:
    for (x = 1; x < 10; x += 1) {
        setTimeout(function () {
            console.log(x);
        }, 10);
    }

    Этот пример при первом запуске породит вывод
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10
    а при втором
    19, 10, 10, 10, 10, 10, 10, 10, 10, 10
    при третьем
    28, 10, 10, 10, 10, 10, 10, 10, 10, 10
    вместо ожидаемого
    1, 2, 3, 4, 5, 6, 7, 8, 9

    который может получиться только при помощи правильного использования механизма видимости имен:
    var f = function (x) {
        setTimeout(function () {
            console.log(x);
        }, 0);
    };
    for (x = 1; x < 10; x += 1) {
        f(x);
    }


    Обязательные блоки



    Строго обязательно использовать блок (оформляется фигурными скобками) при использовании if, for и других инструкций.

    if (condition) statement;
    // надо заменить на
    if (condition) {
    	statement;
    }

    И первый и второй код работают одинаково, однако первого на практике следует избегать.

    Конструкции языка


    for in


    Такого рода циклы надо использовать с осторожностью, поскольку проходя по всем членам объекта или массива, этот цикл также пройдет и по унаследованным свойствам/методам прототипа. JSLint требует чтобы тело такого цикла в обязательном порядке было обернуто блоком if.
    for (name in object) {
        if (object.hasOwnProperty(name)) {
            ....
        }
    }

    switch


    Обязательно использовать break после каждого case

    void


    Не надо использовать это. Лучше обычный undefined, во избежание недопонимания.

    == и !=


    Использовать с особой осторожностью. Необходимо помнить, что эти операторы приводят тип данных, то есть ' \t\r\n' == 0 это true. Лучше использовать === поскольку этот оператор сравнивает и соответствие типов, а приведение делать вручную, используя parseInt(str, radix) там где надо интерпретировать строку как число.

    =


    Оператор присваивания лучше не использовать в качестве условия в if:
    if (x = y) {
    
    }

    поскольку обычно это означает
    if (x == y) {
    
    }

    у читающего такой код обычно возникает недопонимание — может быть здесь ошибка? Если действительно надо использовать такую конструкцию, необходимо указать это явно, используя двойные скобки:
    if ((x = y)) {
    
    }


    Резюме по JSLint



    Здесь приведен не полный перечень требований JSLint, а лишь те, на которые наиболее часто приходится обращать внимание. Думаю, заинтересовавшемуся человеку не составит труда сходить за полным перечнем на JSLint.com. Здесь же хотел бы добавить еще, что для многих редакторов существуют плагины, позволяющие валидировать код при помощи JSLInt по мере ввода. Лично пользовался плагинами для Eclipse и jEdit. Есть плагин под NetBeans. В крайнем случае, можно воспользоваться on-line валидатором.
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 107

      +12
      >Обязательно использовать break после каждого case

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

      case 1:
      case 2:
      case 3: function(); break;

      чем писать везде

      case 1: function(); break;
      case 2: function(); break;
      case 3: function(); break;

      Поэтому мне кажется данный пункт не совсем актуальным.
        +2
        Согласен, бывает и такое. JSLint ругается больше чем надо, этим и ценен. Лучше обратить внимание на его замечание и проигнорировать, чем не обратить внимание на ошибку.
          0
          С этим согласен, просто в тексте статьи это звучит очень категорично и может ввести в заблуждение.
          • НЛО прилетело и опубликовало эту надпись здесь
          +1
          JSLint не ругается на первый пример.

          Видимо, автор топика имел в виду «после каждой группы case». Иногда после последней группы не ставят break, иногда позволяют специально потоку выполнения «проваливаться» в следующую группу… И вот это линту не нравится.
            +1
            Всё верно. JSLint требует чтобы перед case ставился либо break либо case.
            0
            Цитата из выступления Дугласа Крокфорда:
            Однажды кто-то написал мне: «В языке есть оператор switch, в котором можно проваливаться из одного case-выражения в другое, и это достаточно трудно увидеть, читая код. Не могли бы вы добавить предупреждение в JSLint для таких случаев?». Я подумал и ответил, что есть моменты, когда подобные провалы могуть быть удобными. Можно прямо в коде помечать, что так и задумывалось, хотя на самом деле, вы знаете, это не работает. Возможно, в качестве компромисса имеет смысл оставить всё как есть. В конце концов, неплохо иметь такой оператор в языке.

            На следующий день тот же парень прислал мне сообщение об ошибке в работе JSLint. Я запустил отладчик и обнаружил ошибку в switch-операторе, где case-выражение проваливалось в следующее. [Смех в зале.]

            В тот момент ко мне пришло озарение. В карьере программиста бывают моменты, когда вы действительно что-то постигаете. И это постижение трудно даётся. Тогда я получил урок. Теперь я никогда сознательно не даю case-выражениям проваливаться. Благодаря этому я сейчас могу легче замечать случайные провалы case-выражений. Как следствие, я думаю, что моё использование switch-оператора значительно улучшилось.
          • НЛО прилетело и опубликовало эту надпись здесь
              +2
              Во-первых side-effects. Чтобы код можно было сжать точки с запятой должны стоять везде где надо. В javascript необязательность точки с запятой иногда достигается за счет того, что перевод строки считается за разделитель.
              Во-вторых, при командной работе важен единый стиль. Код оформленный правильно, выглядит надежнее и в нем лучше видны ошибки.
              • НЛО прилетело и опубликовало эту надпись здесь
                  +1
                  Если уже выработан командный стиль, подразумевающий отсутствие точек с запятой, то тут уж не попишешь ничего — придется следовать. Но это ограничит рамки команды людьми которые либо уже в команде, либо не особо опытны в javascript и не имеют привычки ставить точки с запятой. Это касательно командной работы.

                  Касательно yui сказать не могу, т.к. пользуюсь другими инструментами (packer, jsmin), которые требуют расстановки запятых. Не знаю, можно ли доверить машине расставить точки с запятой.
                    0
                    В Ассемблере; применяется для комментариев (TASM, MASM) (-:

                    ;=======
                    mov [(t ZoomPanel edi).hWnd], eax
                    ;=== создаю ReBar
                    sub edx, edx
                    push edx [hInst] edx
                    push eax
                    ;---
                    push edx edx; Размеры
                    push edx edx; Координаты

                    mov eax, WS_CHILD or WS_VISIBLE or WS_CLIPSIBLINGS or\
                    WS_CLIPCHILDREN or RBS_VARHEIGHT or CCS_NODIVIDER
                    push eax
                    push edx
                    push ofs strReBarClass
                    push WS_EX_TOOLWINDOW
                    Call CreateWindowEx
                    or eax,eax
                    jz @@exitErr
                    ;======

                    по сути, можно в конце строк ставить, как в js — ничего плохого не будет (-:

                    0
                    Писал длинный коммент, а браузер его скинул, обидно. Придётся кратко.

                    Я за то, чтобы компрессоры кода выкидывали не перевод строки, а точку с запятой, тогда код меньше терял бы в читаемости и проще было бы понять где нашлась ошибка.
                  • НЛО прилетело и опубликовало эту надпись здесь
                      0
                      А что такого особенно хорошего в отсутствии точек с запятой? Их отсутствие не дает ничего, вы даже код без них писать быстрей не будете. А вот элементарно вытянуть код в строчку с удалением пробелов, чтобы он места меньше занимал, вы уже не сможете.
                      • НЛО прилетело и опубликовало эту надпись здесь
                          0
                          многие просто пишут не только на JS, поэтому точка с запятой переходит из других языков, с их стороны это тоже в основном дело привычки, как и с Вашей
                            +2
                            Точка с запятой, отбитая руками:

                            — упрощает работу javascript-интерпретатора;
                            — позволяет достаточно безопасно сжимать код, удаляя пробелы/переносы;
                            — улучшает читабельность кода, код выглядит профессионально (уж точно в js-среде);
                            — набивает руку для работы с другими языками, где (;) часто обязательна;
                            — снижает риск потенциальных ошибок при работе AIS.
                            0
                            от того что Вы вытянете код в строку, он меньше «места» занимать не будет
                              0
                              Почему не смогу, объясните? Точка с запятой без перевода строки — один байт, перевод строки без точки с запятой — один байт.
                              –2
                              Банально код с точками-запятыми выглядит более читабельно
                              • НЛО прилетело и опубликовало эту надпись здесь
                                  –1
                                  не выглядит, он выглядит, банально, так же, только без точек с запятыми
                                  +1
                                  Точки с запятой иногда помогают при нахождении синтаксических ошибкок в коде, таких как незакрытые скобки. Без точек с запятой часто консоль ошибок показывает ошибку в последней строке, а вот с ";" уже видно где что незакрыл.
                                    +3
                                    А вот случай из моей практики для защиты точек с запятыми.
                                    Как-то раз написал для проекта кучку jquery-плагинов и других ништяков. И лежало всё добро по отдельности, по неймспейсу на файл, например, в виде:
                                    (function($){ /*ништячный плагин*/ })(jQuery)

                                    В один прекрасный момент, решил тулзой собирать классы в один файл, чтобы разом отправлять скрипты клиенту. Собрал пакет, сжал с помощью YUICompressor. А ништяки-то и не работают.
                                    Потому что получилась каша:
                                    (function($){ /*плагин 1*/ })(jQuery)(function($){ /*плагин 2*/ })(jQuery) и т.п.
                                      0
                                      С тех пор, ставлю ';' в начале и конце файла.
                                      • НЛО прилетело и опубликовало эту надпись здесь
                                          0
                                          > С тех пор, ставлю ';' в начале и конце файла.

                                          Кстати, если поговорить о «сферических конях в вакууме», то распространённая практика с постановкой точки с запятой вначале (в качестве страховки на случай, если автор предыдущего скрипта не поставил её в конце), действительно, действенна. Однако, если точка с запятой была правильно поставлена в конце скрипта, то ваша точка с запятой вначале создаст Empty Statement, и, соответственно, будет сканироваться, парситься и «тратить время» ;) Но это так — к слову. На практике же, да, вероятно, удобно при использовании нескольких 3rd-party библиотек и скриптов.
                                        +3
                                        Cогласно Ecmascript определённые statements must be terminated with semicolons, точка с запятой обязательна с точки зрения языка, но опциональна для программиста. Если вы выбрали путь опциональной точки с запятой, то вы выбрали путь, где нет ясности, парсер начинает крутиться за вас, автоматически их «расставляя», по сути он исправляет ошибки. В древних доках Javascript это называли эквивалентом compile-time error-correction. К тому же парсеры не всегда делали это правильно, были и баги на этот счёт (может и сейчас есть), сами dev-ы языка настоятельно рекомендуют не полагаться на AIS и ставить всё руками.

                                        Если же говорить о стиле и вкусовщине, то за всё время работы с javascript я встречал принципиальных борцов за лысый правый край всего раза два. Отчаянные белые вороны. Зато принципиальные. ;-)
                                        • НЛО прилетело и опубликовало эту надпись здесь
                                          • НЛО прилетело и опубликовало эту надпись здесь
                                              0
                                              Ну так Вы и в качестве принципиального борца не выступаете :) Так что не стоит принимать на свой счёт ;-)
                                        • НЛО прилетело и опубликовало эту надпись здесь
                                            +1
                                            IE не любит запятые после последнего элемента массива или члена объекта. Бывает, что именно на это и указывает jslint: var a = [1,2,3,]; Хотя для других браузеров все ок.

                                            Думаю, количество предупреждений зависит от реализации. Плагин для jEdit у меня выдает 51 ошибку, потом останавливается с фразой — слишком много ошибок.
                                              0
                                              вообще это стандарт ецдма говорит что в массивах и обьектах после последнего элемента не должно быть запятой, так что в данном случае ИЕ делает правильно =)
                                                0
                                                В объектах — да, в массивах — нет.
                                                  0
                                                  Вы уверены? массив в JS — обьект, и он обязан следовать тем же стандартам что и обьект
                                                    0
                                                    :-) Не обязан и не следует. И да… уверен.
                                                +1
                                                Да, очень это напрягает =) Особенно когда напишешь много кода, а он потом валится в IE (т.к. отлаживается в FF). Самое обидное, что дебаггер номер строки с ошибкой отдает от балды, даже, иногда, на другой файл ругается.
                                              0
                                              спасибо за статью. теперь буду более пристальней проверять свой джаваскрипт код.
                                                +1
                                                очень интересная статья, спасибо!
                                                Только один вопрос:
                                                Может быть в конструкции:
                                                ----------
                                                var f = function (x) {
                                                setTimeout(function () {
                                                console.log(x);
                                                }, 0);
                                                }
                                                for (x = 1; x < 10; x += 1) {
                                                f(x);
                                                }
                                                ----------
                                                стоит поставить точку с запятой по примеру:
                                                ----------
                                                var f = function (x) {

                                                };
                                                ----------
                                                ?
                                                  0
                                                  Вы правы.
                                                  Надо бы встроить в браузер JSLint, чтобы показывал ошибки такого рода :)
                                                  0
                                                  Объясните популярно почему при выполнение этого кода в ФФ сразу пишет одно число (не смотря на таймаут), а только потом (уже согласно таймауту) все остальные?
                                                  for (x = 1; x < 10; x += 1) {
                                                      setTimeout(function () {
                                                          console.log(x);
                                                      }, 1000);
                                                  }
                                                    0
                                                    потому что цикл выполниться сразу, без задержек
                                                    и создаст в очереди 10 функций, которые ссылаются на глобальную для них переменную Х
                                                    которая соответственно в этот момент уже равна 10
                                                      0
                                                      Вы не ответили на мой вопрос. Переформулирую:
                                                        +1
                                                        Попробуйте лучше это:
                                                        for (var x = 1; x < 2; x += 1) {
                                                            setTimeout(function () {
                                                                console.log('x = ' + x);
                                                            }, 2000);
                                                        }
                                                        'stop';
                                                        

                                                        Первый вывод — это результат выполнения команд в консоли, который получается немедленно, далее — то что по таймеру.
                                                          0
                                                          Спасибо за объяснение. Действительно, выписывается последнее значение, которое возвращает setTimeout

                                                          for (var x = 1; x < 12; x += 1) {
                                                               setTimeout(function(){}, 2000);
                                                          }

                                                      –4
                                                      Я могу предположить что он видя function выполняет её, затем ставит таймаут, посредствам которого выводит оставшиеся числа. С чем связано такое поведение, остаётся только догадываться.
                                                      0
                                                      какой смысл в if ((x = y)) {

                                                      сокращение кода на одну строчку и необходимость обернуть блок кода в кавычки?
                                                        +1
                                                        Иногда так пишут чтобы визуально показать неотделимость блока от результата выполнения какой-то функции. Например
                                                        if ((result = try_to_fetch_result())) {
                                                            do_something_with_result(result);
                                                        }
                                                        
                                                          +1
                                                          Кстати я замечал у джавистов и сишников полезную привычку — в if'ах сначала писать константу при сравнивании:
                                                          if (SOME_CONSTANT == var) {…

                                                          if ('text' == str) {…

                                                          Такая конструкция идет несколько коробит восприятие (я так подозреваю, что только сначала, во время привыкания), но значительно уменьшает вероятность провести много времени в жестоком дебаге из-за = вместо ==.
                                                            0
                                                            Ну насколько я помню, такая привычка больше связана с вероятностью, что переменная может быть пустой. И тогда оператор == может вызвать ошибку, так как не определён для пустого объекта. В случае же, когда сначала пишется константа, она является вполне конкретным объектом, для которого оператор сравнения определён. И эксепшена не будет.
                                                              +2
                                                              На самом деле, это защита от опечаток, когда вместо == ошибочно набирают =.
                                                              Например, следующий код скомпилируется, но условие никогда не выполнится:
                                                              int a = getValue(); if (a = 0) { /*code*/ };
                                                              А если поставить константу в начало, то компилятор выдаст ошибку о том, что операция присваивания не валидна:
                                                              int a = getValue(); if (0 = а) { /*code*/ };
                                                                0
                                                                Что-то мне подсказывает, что Вы ошибаетесь. Оператор == униполярный, т.е. нет никакой разницы в порядке указания операндов. И если один из них не определен и в силу особенностей языка не сможет быть в таком виде приведен к какому-то сравнимому с другим типу, то ошибка произойдет в любом случае, будь он слева или справа. А вот ошибиться и присвоить переменную вместо сравнения легко.
                                                                  0
                                                                  Очевидно, мои воспоминания идут из каких-то совсем давних времён. Ибо с описанной мною проблемой сталкивался лично, но как-то очень давно.
                                                            0
                                                            Спасибо, буду использовать.

                                                            Как он к коду jquery относится? Я имею ввиду если писать с использованием методов jquery, он их валидирует, плюёт или кучу варнингов выдаёт?
                                                              +1
                                                              Для использования jQuery я пишу /*global jQuery, $ */ и JSLint не ругается. По сути же jQuery — это две глобальные переменные, не на что там больше ругаться. Вообще говоря, по jQuery и правилам хорошего тона использования можно еще целую статью написать.
                                                                0
                                                                напишите :)
                                                              +1
                                                              Хорошая вещь, но, ИМХО, фанатично верить ей тоже не стоит.
                                                              Как правильно сказано — не панацея.
                                                              На некоторые вещи Линт ругается с видом цепного пса, которому кидают косточку по одной за каждый гавк.)
                                                                0
                                                                Удалось ли заставить JSLint не ругаться на неопределённую переменную $? Мне в globals её два года назад не удалось вставить, может что-то изменилось?
                                                                  0
                                                                  /*global $ */ работает для меня
                                                                  0
                                                                  А desktop или какой-либо stand-alone версии нету?
                                                                  0
                                                                  Кстати, неплохобы было прикрутить его как плагин к Eclipse\Aptana\NetBeans\Visual Studio :)
                                                                    +2
                                                                    Уже прикручено как минимум в Eclipse\Aptana\NetBeans. Про Visual Studio сказать не могу, так как не юзал. Вот тут говорят, что есть и для VS: www.codeproject.com/KB/macros/JSLintVS.aspx
                                                                      0
                                                                      Поделитесь пожалуйста ссылкой или руководством, как для Eclipse сделать?
                                                                    +2
                                                                    Сначала когда только начал писать код на XUL+javascript использовал JSLint чтобы найти синтаксическую ошибку в js-коде. Сейчас javascript-код пишу в Komodo Edit. Он находит и подсвечивает ошибки в коде. Правда конечно не так придирается к коду как JSLint, но зато не нужно туда-сюда копировать код чтобы найти ошибку.
                                                                      0
                                                                      ошибки в коде может и NetBeans подсветить + ошибки css, html, php
                                                                      0
                                                                      В целом довольно логичные и правильные правила. И не только для js.
                                                                        0
                                                                        У меня с линтом связан курьезный и идиотский, на мой взгляд, случай.
                                                                        При удачном собеседовании и написании тестового задания, я не был принят на работу по причине того, что мой код не прошел валидацию JSLint'ом. По сути там было только одно критичное замечание — я не сделал проверку на hasOwnProperty в конструкции for (var in object). В остальном, «специалист» долго дрючил мне мозги за лишние точки с запятой: после function, for,… и лишние пробелы в конструкциях типа if (element.parentNode && Math.max(offset1, offset2, offset3) > x1).
                                                                          +1
                                                                          > При удачном собеседовании и написании тестового задания, я не был принят на работу по причине того, что мой код не прошел валидацию JSLint'ом.

                                                                          Это не собеседование, а хрень на постном масле. К чёрту такие конторы.

                                                                          > В остальном, «специалист» долго дрючил мне мозги за лишние точки с запятой

                                                                          Вы правильно сделали, что ушли оттуда.
                                                                            0
                                                                            Это скорее не контора, а человеческий фактор. Насколько я помню это была компания Oberon Media, один из лидеров казуальных и онлайновых игрушек. И я, честно говоря, весьма хотел там работать, собеседование с HR мне понравилось, деньги и условия предлагали интересные. Скорее всего было как-то так: «Ты! Через 5 мин ты проводишь собеседование». А если человек не знает, как проводить это собеседование и абсолютно не готов к нему, начинается всякий бред.
                                                                          0
                                                                          Большинство правил итак соблюдаю. Единственное, при итерации всегда объявляю переменную в конструкции for, как-то некомфортно мне ее объявлять за пределами, так как используется только внутри.
                                                                            0
                                                                            Качество кода у меня чаще страдает из-за отсутствия модификаторов доступа. Бывает, слишком увлекаюсь, потом объекты наглухо привязаны друг к другу. В последнее время борюсь с этим префиксом "_". Еще иногда увлекаюсь замыканиями, но это как правило легко рефакторится.
                                                                            +2
                                                                            иронично, что автор самого JSLint Douglas Crockford сказал следующее: In most of the classical languages, the language is the thing imposing the discipline. In Javascript you have to bring your own discipline.

                                                                            на русский это переводится приблизительно так: В большинстве классических языков сам язык принуждает к дисциплине. В яваскрипте вам нужна собственная дисциплина.

                                                                            у меня достаточно собственной дисциплины, чтобы не пользоваться костылями вроде JSLint
                                                                              –1
                                                                              > у меня достаточно собственной дисциплины, чтобы не пользоваться костылями вроде JSLint

                                                                              ага ;)
                                                                                0
                                                                                Ой, да ладно, минусовать-то сразу ;) Я хотел сказать, что не нужно её воспринимать как «спасение» от «выдуманных проблем». В целом же — тулза, конечно, полезная.
                                                                                0
                                                                                Вчера его как раз слушал на конференции. Не впечатлил. Говорил про секурность в браузерах. Так вот, на вопрос «кто использует jslint?», в зале полном веб программистов и дизайнеров поднялось всего 2 руки.
                                                                                  0
                                                                                  некоторые вещи он правильно говорит
                                                                                  а к jslint отношение разное бывает
                                                                                    0
                                                                                    Ничего не имею против него, и говорил он правильные вещи о которых я сделал себе пометочки и идеи, которые пришли в голову в тот же момент. Но лично меня он не впечатлил, и предлагаемые решения тоже. И на вопрос «а сколько человек/компаний пользуются вашим решением?» (речь про безопасность веб-приложений) Он ответил — «два — я и ...». Скорее всего хотел пошутить, но думаю он недалек от реального положения дел. Зал тоже не особо бурно реагировал на его выступление. В общем популязатор своих или чьих-либо еще идей он никакой.
                                                                                0
                                                                                > В javascript глобальные переменные можно объявить в локальном контексте, что только усугубляет ситуацию, потому что иногда можно объявить глобальную переменную по ошибке

                                                                                Касается не столько ошибок объявления свойств глобального объекта, а просто уточнение — переменные объявляются только с ключевым словом var. Обычное же присвоение, создаёт свойство глобального объекта, но не переменную. Соответственно, нельзя объявить глобальную переменную в локальном контексте.

                                                                                > который может получиться только при помощи правильного использования механизма видимости имен:

                                                                                Вариант с обрамляющим контекстом (в виде новой внутренней функции) — не единственный, чтобы замкнуть нужное значение. Поэтому слово «только» может смущать. С одной стороны оно может относится с слову «правильного» (и это верно), с другой — может подразумевать, что данный способ — единственный, что неверно.
                                                                                  0
                                                                                  Не хватает еще упоминания, что JsLint можеть делать проверку на соответствие правилам ADsafe.
                                                                                    0
                                                                                    Вопрос к автору: а зачем вы выделили тело цикла в отдельную переменную f? Не проще ли было написать

                                                                                    for (x = 1; x < 10; x += 1) {
                                                                                    (function (x) {
                                                                                    setTimeout(function () {
                                                                                    console.log(x);
                                                                                    }, 0)
                                                                                    }(x));
                                                                                    }
                                                                                      0
                                                                                      Думаю, так понятнее для нубов. Кроме того, JSLint предупреждает, что использовании анонимых функций в циклах. Ваш пример с точки зрения JSLint'a должен быть таким:
                                                                                      for (var x = 1; x < 10; x += 1) {
                                                                                      	setTimeout(function (x) {
                                                                                      		return function () {
                                                                                      			console.log(x);
                                                                                      		};
                                                                                      	}(x), 0);
                                                                                      }
                                                                                      
                                                                                        0
                                                                                        Странно, у меня не ругнулся, вот законченый пример:

                                                                                        /*global setTimeout, console */
                                                                                        for (var x = 1; x < 10; x += 1) {
                                                                                        (function (x) {
                                                                                        setTimeout(function () {
                                                                                        console.log(x);
                                                                                        }, 0);
                                                                                        }(x));
                                                                                        }

                                                                                        (Проверял через сайт; в исходном варианте ругнулся только на точку с запятой и глобальные переменные.)
                                                                                          0
                                                                                          > Кроме того, JSLint предупреждает, что использовании анонимых функций в циклах

                                                                                          А почему?

                                                                                          Кстати, результат в вашем примере другой будет.
                                                                                            0
                                                                                            x += 1 вместо ++x это считается за повышение качества кода? ;-)
                                                                                              0
                                                                                              крокфорд настаивает, что ++ вредно использовать
                                                                                                0
                                                                                                Вредно чем? Аргумент, что код «too tight, too tricky, too cryptic» не канает вообще, уж для ясного и солнечного for-in точно. Я как это вижу: x+=1, у меня сразу 2 вывода в голове:

                                                                                                a) он не знает операторов;
                                                                                                б) он болеет крокфордизмом.

                                                                                                ;-)
                                                                                                  0
                                                                                                  не for-in, а for конечно же.
                                                                                                    0
                                                                                                    для него этот аргумент канает, может быть, и в случае for тоже
                                                                                                      0
                                                                                                      Вкусовщина, в общем. ок
                                                                                                    0
                                                                                                    Я болен точно. И, кстати, не только Крокфорд, но и Макконнелл пишут о том что x++ и ++x надо использовать с осторожностью.
                                                                                                      0
                                                                                                      Что может случиться в js, если я буду неосторожен и напишу:

                                                                                                      for ( var i = 0; i < a.length; ++i ) {

                                                                                                      }

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

                                                                                                        Я, кстати, не против использовать в этом контексте i++. Но, поскольку использую JSLint, пишу без варнингов, просто чтобы не пропустить чего-то действительно важного. Плюсы очевидны — операции инкремента всегда однообразны, что не заставляет читателя кода каждый думать о несущественном с одной стороны, а с другой стороны — дает мне, как пишущему программу, понять, что код — это не место для соревнования, кто хитрее напишет. Лично я против любой самодеятельности типа ++i там где можно обойтись i += 1. Но вообще говоря, если принятый стандарт требует обратного — я буду так же ратовать за использование ++i. Главное, чтобы везде было одинаково и не возникало вопросов, ни как писать, ни как читать такой код.
                                                                                                          0
                                                                                                          > В любом случае, поток мыслей его прервется из-за использования нестандартного элемента в стандартной ситуации.

                                                                                                          Именно так и случается со мной, когда я в 'for' вижу i+=1 Поток мыслей моих тут же прерывается из-за использования нестандартного элемента в стандартной ситуации. Вы много js-кода видели в таком вот русле крокфордизма? Что стандартней, если считать просто по объёму?

                                                                                                          Можно ещё с натяжкой понять про '===' вместо '==', но инкремент внутри 'for' давить безо всяких причин… это перебор. ;-)
                                                                                                            0
                                                                                                            В данном случае, согласен, имеет место перегиб. Сейчас перепроверил даже свои настройки — мой JSLint не ругается на ++ и --

                                                                                                            Но и ++i в данном контексте сбивает с толку. Согласитесь, что для цилклов стандартнее i++
                                                                                                              0
                                                                                                              Для обычного простого 'for' не важно пост или пре. Можно и так, и так. В своё время пре тестили, и он считался более быстрым (чуть другой алгоритм по сравнению с пост), как сейчас — не знаю, тут уж дело привычки.
                                                                                                            0
                                                                                                            ничего не имею против ++ /- -, но вчера на конференции(fronteers 2009) в докладе уважаемого Thomas Fuchs следующий кусочек не только меня поставил в тупик:
                                                                                                            ~~(какие-то вычисления)
                                                                                                            
                                                                                                            Оказалось двойное отрицание — это просто конверсия числа в int. Вместо Math.floor() для экономии размера кода.
                                                                                                              0
                                                                                                              > Вместо Math.floor() для экономии размера кода.

                                                                                                              Иногда не только экономия размера кода имеет место быть, но и, также, экономия в скорости, как, например, в преобразовании строкового представления в число. Когда однозначно известен формат числа (включая систему счисления), то часто быстрей и удобней использовать ведущий плюс для преобразования (в альтернативу, например parseInt)

                                                                                                              var str = '10';
                                                                                                              alert(typeof +str); // number
                                                                                                                0
                                                                                                                Это он у меня украл :) twitter.com/thomasfuchs/statuses/5292217697
                                                                                                                0
                                                                                                                > Человек, возможно не очень хорошо знающий нюансы языка

                                                                                                                Ну так а в чём проблема? Значит надо садиться и изучать язык.

                                                                                                                Это как, например, математика. Есть школьный уровень. Есть уровень техникума. Университета. Академический уровень.

                                                                                                                Так вот, скажите мне, — с какой стати я должен писать на уровне математики 6 класса школы, чтобы код был понят каждым новичком после прочтения книги «Этот занимательный Javascript»? И это не относится сейчас к конкретному случаю с «x++» или «x += 1».

                                                                                                                Естественно, основным критерием, в общем случае, должна являться простота чтения кода. Но только не надо перебарщивать, приводя аргументом, что код не поймут новички, которые только прочли первую главу книжки.

                                                                                                                В частных случаях, где критерием может быть максимальный выжим ресурсов, могут использоваться нестандартные хакерские способы — но здесь нечитаемость будет уже оправдана.
                                                                                                          0
                                                                                                          > крокфорд настаивает, что ++ вредно использовать

                                                                                                          Дедушка Крокфорд, действительно, внёс немалый вклад в JS (в основном, прикладного характера). Но только вот не делайте из него «икону», а? Он далеко не безупречен в JS, тоже ошибается, местами знает JS поверхностно, и мысли его порой субъективные.

                                                                                                          Если вы будете постоянно «полагаться на истину авторитета, вместо того, чтобы полагаться на авторитет истины, вам будет нелегко» донести свою точку зрения.
                                                                                                            0
                                                                                                            я разделяю ваше отношение к крокфорду, хотя и не считаю, что он внёс вклад в JS, кроме JSON
                                                                                                    0
                                                                                                    Problem at line 169 character 13: eval is evil.
                                                                                                    eval( 'var list = ' + strList );

                                                                                                    :-D разработчики с чувствою юмора
                                                                                                      0
                                                                                                      Для меня JSLint тоже средство совершенно незаменимое, т.к. сам разрабатываю довольно непростой фреймворк (для карт). Особенно критичны две вещи: точки с запятыми (чтобы код не ломался после сборки различного рода компрессорами — сам пользуюсь рубишным packr, работающим по алгоритму Крокфорда) и отсутствие глобальных переменных (узкоспециализированный фреймворк не может себе такого позволить, чтобы избежать конфликтов с другими).

                                                                                                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                                                                      Самое читаемое