JavaScript代碼檢查工具 — JSHint

靜態代碼檢查是開發工做中不可缺乏的一環,畢竟對於程序化的工做人的眼睛是不可靠的,更況且是本身的眼睛看本身的代碼。即便最後的運行結果經過,但可能存在一些未定義的變量、定義了但最後沒用過的變量、分號有沒有加(看團隊規則)以及其餘的問題。給力的工具必不可缺。javascript

在本文要介紹的JSHint以前還有JSLint,道格拉斯的做品,應該是JavaScript精粹的附屬產物。。。要求你必須使用它的規則,對於JavaScript這樣一個靈活的語言,仍是要用一個靈活的工具,JSHint就是就是這樣。java

安裝

首先須要安裝了Nodejs和npm,而後 npm install -g jshint 就行了。node

這樣你就可使用命令行使用JSHint了。git

固然他也提供了巨多的編輯器插件,好比Sublime Text 3github

以及Grunt或者Gulp之類的插件。ajax

配置

安裝完了就可使用了。npm

命令行下直接: jshint myfile.js 就ok,命令行裏就能夠顯示錯誤或者警告。windows

編輯器下通常直接顯示在出錯或者警告的行數處。好比Sublime3 下,在當前文件下,快捷鍵 Ctrl+Alt+J 就會顯示信息( Ctrl+Alt+C 關閉信息顯示):數組

更多快捷鍵看插件的設置,能夠自定義。瀏覽器

不過這些顯示都是JSHint默認的配置,咱們能夠自定義配置更好的知足需求。

也很簡單,在項目根目錄下創建一個 .jshintrc 文件,這個文件就是JSHint的配置文件,JSHint會自動識別這個文件,根據這裏面的規則對你的文件進行檢查。

(windows下創建前面帶點的文件會不讓創建,一種方法直接在Sublime Text裏創建,另外一種方法在文件名後加個點便可)

JSHint的配置分爲四類:

一、Enforcing:若是這些屬性設置爲true,代表這個代碼風格夠嚴格的,好比是否使用嚴格(strict)模式、變量駝峯式命名、是否是for-in循環裏必須得有hasOwnProperty等等

二、Relaxing:好比是否使用分號,是否支持下一代ES語法等等。

三、Environments:你的代碼所在的環境(Nodejs、瀏覽器、jQuery。。)

四、自定義的全局屬性,好比我司的NEJ和Regular,這兩個全局變量JSHint是不知道的,放在這裏JSHint不會報出錯誤信息。

默認的JSHint的配置看這裏:JSHint默認配置(Sublime插件自定義了默認的配置,你能夠在插件的配置裏看到,甚至能夠直接修改它)

對這些配置的講解:配置詳解

都是英文的,不過配合着四六級的水平和有道翻譯,基本木有問題。下面是一個簡單的配置示例。

{
    "strict"   : false,
    "undef"    : true,     
    "unused"   : true,

    "asi"      : true,
    "evil"     : false,

    "browser": true,
    "devel": true,

    "globals"  : { 
        "NEJ": true,
        "Regular": true
    }        
}

 

有時候,咱們不但願它檢查一些文件(好比一些庫文件),這時候能夠新建一個 .jshintignore 文件,把須要忽略的文件名寫在裏面(支持通配符),一樣放到項目根目錄下便可。

build/
src/**/tmp.js

 

自定義Reporter

JSHint源碼裏有一個reporter.js,定義錯誤提示信息改怎樣輸出,一樣能夠自定義。默認的是這樣的:

"use strict";

module.exports = {
  reporter: function (res) {
    var len = res.length;
    var str = "";

    res.forEach(function (r) {
      var file = r.file;
      var err = r.error;

      str += file + ": line " + err.line + ", col " +
        err.character + ", " + err.reason + "\n";
    });

    if (str) {
      process.stdout.write(str + "\n" + len + " error" +
        ((len === 1) ? "" : "s") + "\n");
    }
  }
};

基本的格式就是:

module.exports = {
  reporter: function (reporter) {
    //....
  }
};

每一個reporter都符合必定的格式:

{
  file:        [string, filename]
  error: {
    id:        [string, usually '(error)'],
    code:      [string, error/warning code],
    reason:    [string, error/warning message],
    evidence:  [string, a piece of code that generated this error]
    line:      [number]
    character: [number]
    scope:     [string, message scope;
                usually '(main)' unless the code was eval'ed]

    [+ a few other legacy fields that you don't need to worry about.]
  }
}

好比你可讓他不輸出到控制檯而是打印到txt文件裏(不知爲什麼異步寫入文件一直不成功,最後只好用同步函數):

'use strict';

var fs = require('fs');

module.exports = {
  reporter: function (res) {
    var len = res.length;
    var str = '';
    var filename = '';

    res.forEach(function (r, i) {
      filename = r.file;
      var err = r.error;

      if(i === 0) str += filename + '\n';

      str += 'line ' + err.line + ', col ' +
        err.character + ', ' + err.reason + '\n';
    });

    if (str) {
      var output = str + '\n\n';
      fs.writeFileSync('message.txt', output);
    }
  }
};

命令行執行:

jshint --reporter=myreporter.js myfile.js

一樣能夠更近一步,若是你想一下把全部該檢查的文件全都檢查了,而後將檢查結果保存到txt裏:

// code-check.js
var
fs = require('fs'); var path = require('path'); var exec = require('child_process').exec; var curPath = path.join(process.cwd(), 'src', 'javascript'); function travelDir(dir, callback) { fs.readdirSync(dir).forEach(function(file) { var pathname = path.join(dir, file); if(fs.statSync(pathname).isDirectory()) { travelDir(pathname, callback); } else { callback(pathname); } }); } fs.writeFileSync('message.txt', ''); travelDir(curPath, function(file) { exec('jshint --reporter=reporter.js ' + file); });
// reporter.js
'use strict'; var fs = require('fs'); module.exports = { reporter: function (res) { var len = res.length; var str = ''; var filename = ''; res.forEach(function (r, i) { filename = r.file; var err = r.error; if(i === 0) str += filename + '\n'; str += 'line ' + err.line + ', col ' + err.character + ', ' + err.reason + '\n'; }); if (str) { var output = str + '\n\n'; fs.appendFileSync('message.txt', output); } } };

只要  node code-check 就能夠了。

不過,Sublime插件下不知道如何自定義。

 

API 

JSHint暴漏了一些接口,既能夠在瀏覽器也能夠在Nodejs中使用。

瀏覽器下首先加載jshint.js文件:

<script src="node_modules/jshint/dist/jshint.js"></script>

首先檢查js語句是否存在錯誤:

 var result = JSHINT(source, options, predef) 

source是你要檢查的代碼,能夠是字符串,也能夠是數組,數組的話每一項表明一行代碼。

options也上面說過的配置項,但不包括Globals

predef是上面說過的Globals

當result返回false的時候,表明語句中有錯誤,這時候調用 JSHINT.data() 就會獲得錯誤的詳細信息,看下面的示例:

var source = [
    'function() { console.log("a") }',
    'x = 3'
]
var options = {
    undef: true
}
var predef = {
    x: true
}
var result = JSHINT(source, options, predef)

console.log(JSHINT.data())

瀏覽器的控制檯就會輸出錯誤的詳細信息,這樣咱們甚至能夠作一個錯誤報告出來,就像公司內部的代碼檢查平臺 同樣。

不過有個問題,不可能咱們把代碼一行一行的敲到參數裏,ajax或者服務器端請求都行,看這裏

因此嘛,仍是在node環境下使用最方便:

// check.js
var
JSHINT = require('jshint').JSHINT, fs = require('fs'), files = []; process.argv.forEach(function(val) { files.push(val) }) console.log('-----------------------------------------') for(var i = 2; i < files.length; i++) { fs.readFile(files[i], function(err, data) { if(err) { console.log('Error: ' + err) return } if(JSHINT(data.toString())) { console.log('File ' + files[i] + ' has no errors!') } else { console.log('Errors in file ' + files[i]); console.log('') var out = JSHINT.data(), errors = out.errors; for(j = 0; j < errors.length; j++) { console.log(errors[j].line + ': ' + errors[j].character + ' -> ' + errors[j].reason + ' -> ' + errors[j].evidence); } console.log('') console.log('Globals: ') for(var j = 0; j < out.globals.length; j++) { console.log(' ' + out.globals[j]); } } console.log('---------------------------------------------') }) }

使用的時候 

node check a.js b.js c.js

最後在控制檯輸出錯誤。

 

有時候掌握一個工具工做效率會提升不少倍,學會作一個懶人。

相關文章
相關標籤/搜索