Přejít k navigační liště

Zdroják » JavaScript » Kontrola JavaScriptu s JSLint a JSHint

Kontrola JavaScriptu s JSLint a JSHint

Články JavaScript, Různé

V článku si představíme dva podobné nástroje, které vám mohou ušetřit čas při programování statickou kontrolou kódu v JavaScriptu. Zkontrolují, zda dodržujete jednotná pravidla zápisu kódu a upozorní vás na případné syntaktické chyby, překlepy, ale i na „zapomenuté“ příkazy, proměnné či nejasné konstrukce.

JSLint

JSLint je nástroj pro kontrolu kvality kódu. Jeho autorem je známý vývojář a propagátor Douglas Crockford (bude hostem na letošním WebExpo – pozn.red.). Nástroj JSLint provede statickou analýzu a upozorní na místa, která by mohla způsobit problémy. Používání JSLintu nutí programátora dodržovat určité konvence. Výsledkem je kód, u něhož je konzistentní coding standard, což pomáhá eliminovat mnohé zásadní chyby.

Abychom si udělali lepší představu o tom, co JSLint dokáže, přejdeme rovnou k jednoduchému příkladu. Představme si, že náš zdrojový kód obsahuje mimo jiné tuto podmínku (s „chybou“):

if (a = b) {
    // nejaky korektni kod
}

Bystrý čtenář si povšimne, že došlo zřejmě k chybě z nepozornosti či k překlepu a proměnné se v podmínce neporovnají, ale přiřazují. JSLint v takovém případě vypíše pozici chyby a zprávu:

Expected a conditional expression and instead saw an assignment.

Instalace a použití

JSLint existuje jako online nástroj (JSLint online), ale lze jej použít i offline. Stáhněte si aktuální verzi z GitHubu:

git clone https://github.com/douglascrockford/JSLint

V aktuálním adresáři se vytvoří adresář se staženým projektem. Hlavní soubor, který nás zajímá, je jslint.js. V něm se nachází globální funkce JSLINT. Použití s implicitním nastavením je snadné:

var myResult = JSLINT(source, options);

V proměnné source se nachází řetězec s kódem určeným ke kontrole. V myResult bude hodnota true, pokud byl kód podle JSLint správný, jinak false. V globálně dostupném poli JSLINT.errors budou pak jednotlivé chyby, vždy s číslem řádku, popisem problému a dalšími informacemi.

Druhý parametr je volitelný parametr, který obsahuje nastavení pravidel.

Používáte-li nějaký specializovaný editor, může být JSLint dostupný jako plugin. Některé pluginy do editorů mohou mít ale jiné nastavení, např. plugin pro VIM nevyžaduje mezeru za ‚if‘ a naopak chce středník za každým příkazem.

Podívejme se teď na část pravidel, které JSLint obsahuje. A nezapomeňte na autorovo varování: JSLint will hurt your feelings.

Typová kontrola

var i = 0;
i = "a";
Type confusion: 'i': number and 'a': string.

Přestože JavaScript není staticky typovaný jazyk, JSLint dokáže v tomto případě rozpoznat, že jste do číselné proměnné chtěli uložit řetězec.

Operace inkrementace a dekrementace

Tyto operace jsou zakázány, neboť bývají zdrojem záludných chyb. Jsou povolené jen v cyklu for.

Vytváření objektů

var a = new Object();
Use the object literal notation {}.

JSLint vyžaduje specifický zápis pro nové objekty. Proč nám nutí jinou notaci, když je to „to samé“? Důvody jsou následující:

  • syntaxe je mnohem kratší
  • elegantněji se vytvářejí objekty za běhu:
    {name: "Bob", age: 8}

Povinné středníky

var foo = function () {
    //...
}

Středníky jsou v JavaScriptu nepovinné (resp. existují poměrně komplikovaná pravidla, která říkají, kde si má interpret středník „domyslet“). Výsledkem je, že pokud k předchozímu kódu připíšete něco takového:

(function () {
    //...
})();

bude celý kód interpretován jako

var foo = function () {
    //...
}(function () {
    //...
})();

Druhá funkce se stane parametrem pro volání té první, a výsledek se bude volat jako funkce. Tedy něco jiného, než jsme zamýšleli. Proto JSLint na střednících trvá.

Eval je zlo

Přiznejme si, že spouštět kód v řetězci není úplně nejčistší řešení. Kód v řetězci není vizuálně strukturovaný, editory běžně nezvýrazňují syntax JavaScriptu v řetězcích, a to ani nemluvíme o možných bezpečnostních rizicích, spojených s neošetřeným vstupem funkce eval().

Nedosažitelný kód

JSLint kontroluje, zda za příkazy jako return, které „odkloní“ běh programu, není nějaký další kód. Pokud je, upozorní na to.

JSLint dovede uživatele zahltit slušnou řádkou zpráv i při poměrně banální chybě. Vyplatí se nejdřív podívat na daný řádek a zamyslet se, co je špatně, než mechanicky chybu po chybě napravovat.
Některá varování JSLint mohou být až nesmyslná a mohou vás pěkně vytočit. Dejte ale Douglasovi šanci a najděte si, co to varování znamená – většinou má nějaký smysl. Pokud vám ale některá varování opravdu nevyhovují a považujete je v dané situaci (nebo obecně) za nesmyslná, můžete některá z nich potlačit v konfiguraci.

Závěrem: JSLint nám dává možnost zamyslet se nad způsobem, jakým píšeme v JavaScriptu, a nad návrhem jazyka ECMAScript jako takového.

JSHint

Jestliže se vám zdá JSLint příliš radikální a omezujíci, JSHint by mohlo být to pravé. Jeho autory rozčiloval fakt, že JSLint nutil programátory psát jako Douglas Crockford. Proto vznikl fork z verze 2010–12–16. Ten je méně pedantický a dostal jméno JSHint. Jeho vývoj je řízený komunitou a klade důraz především na respektování odlišných programovacích stylů. Je možné nastavit kontrolu každého pravidla, které chceme dodržovat.

git clone https://github.com/jshint/jshint.git

Použití offline verze je stejné jako u JSLint, jen se používá funkce JSHINT.

Konstrukce, které JSLint zakazoval, je možné v JSHint povolit. Například operátor přiřazení v podmínce, podmínka bez složených závorek, funkce eval… Navíc je u JSHint možné specifikovat i prostředí (prohlížeč, jQuery/Prototype atd.), které používáme. JSHint tak rozpozná příslušné globální proměnné a nehlásí „planý poplach“.

Jako materiál pro článek byla použita JSLint edice 2011–07–01, JSHint edice 2011–04–16, Ubuntu 11.04.

Komentáře

Subscribe
Upozornit na
guest
18 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
tdvorak

Dovolím si přihodit odkaz na návod, jak spustit takovou validaci z příkazové řádky, třeba v rámci continuous integration: http://www.tomas-dvorak.cz/clanky/jshint-a-spousteni-validace-javascriptu-z-prikazove-radky . Třeba to někomu pomůže zaintegrovat do vývojového procesu.

srigi

Tahat kvoli tomuto JRE na server mi nepride ako najlepsi napad. Predpokladam, ze navod vznikol este v dobe, ked nebol v kurze Node.js, ktory sa predsalen hodi na server viac.

tdvorak

Nn, naopak sem nemel potrebu pouzivat node.js kdyz jre pouzivam pro kvanta jinych veci v ramci CI. Navic cely projekt nam bezi na jave, proste ji mame vsude :) Ale pokud nekdo nalinkujete implementaci pro debian v node.js, rad se priucim ;)

Srigi

Uh, reagoval som prehnane rychlo a nedoslo mi, ze aj serverove aplikacie sa pisu v Jave. Dopleteny zo vsetkych tych dynamickych jazykov.

Čelo

No tak jsem zkusil prohnat výsledek z CoffeScriptu přes JSLint a JSHint na vzorový kód „square = (x) -> x * x“
Přes JSHint prošel ok, ale JSLint opravdu hází věci typu:
– Expected exactly one space between ‚function‘ and ‚(‚.“
– Expected ‚return‘ at column 5, not column 3.
Bližší mi zůstane asi JSHint

2X4B-523P

JavaSlint :-D

Jerry

Autor JSLintu o svém „čístém“ JavaScriptu, který ten program vynucuje, napsal dokonce celou knihu, jmenuje se to JavaScript: The Good Parts. Myslím v článku o tom zmínka není.

Jinak, tenhle přístup má asi něco do sebe, například v Google Go se projevuje v podobě nástroje gofmt, což je automatický formátovač kódu, jazyk tím má definovaný „jediný správný“ způsob odsazování atd.

DavidDurman

Za zminku urcite stoji i Zeon.js (zeonjs.com). Je to kompletne v JavaScriptu napsany parser, generuje AST a provadi nad nim analyzu kodu. Velice pokrocily nastroj. Dokaze provadet analyzu real-time pri psani kodu. Reparsuje kod po kazde zmene pritom odezva je okamzita.

pb

ako kontrolovat cez JSLint kod, ked je rozdeleny do viacerych zdrojovych suborov?

tdvorak

iterovat pres vsechny *.js soubory a nad kazdym z nich spustit kontrolu?

pb

problem je, ze pri kontrole JSLint napise, ze nepozna nejaku funkciu, ale ta je pritom dostupna v dalsom subore…
jedine riesenie zatial vidim v docasnom zluceni vsetkych suborov kvoli kontrole… (prip. v ignorovani takych chybovych hlaseni)

asdasd

Díky za tip na JSHint, JSLint jsem přestal používat proto, že autor do něj začal cpát svoje představy o jediném správném zápisu kódu a znechutilo mě prodírat se kupou nepodstatných hlášek, jako „Expected exactly one space between ‚)‘ and ‚event'“.

blizz

if (a = b)
{

}

ale ono to neni chyba proste priradím do premennej „a“ hodnotu premnnej „b“ a premennú „a“ potom testujem či má hodnotu true

David Hrachový

Ano, máte pravdu. Proto jsem slovo ‚chyba‘ dal do uvozovek, aby se to nebralo doslova.

tdvorak

Zato je to krasne krypticky kod, az pak budete hledat chybu, takovy zapis v pohode prehlednete. Proto se pred tim obecne varuje ;)

juraj

Netvrdím, že používať eval je správne, ale argument „a to ani nemluvíme o možných bezpečnostních rizicích, spojených s neošetřeným vstupem funkce eval()“ je v spojení s Javascriptom úplná hlúposť. Javascript beží u klienta, teda mi umožňuje spustiť akýkoľvek kód alebo bežiaci kód akokoľvek modifikovať. Bez ohľadu na to, či tam eval mám, alebo nie.

Opravdový odborník :-)

To se asi týká případu, kdy hodnota přijde jako GET parametr (tedy potenciálně od útočníka, který poslal oběti odkaz), projde skrz server, kde se dostane do řetězce určeného pro eval() a na straně klienta se vykoná jako JavaScript a má stejná práva jako kód z dané domény (přestože pochází z jiné, od útočníka).

juraj

Ak je programátor taký idiot, že Javascriptový kód pchá do query stringu, je to rovnako deravé, či sa použije, alebo nepoužije eval.

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.