前端開發環境准備好了,我們准備開始進行開發。
前端開發的主力語言是 JavaScript,這是一種腳本語言,沒有編譯器,也就沒有了編譯器帶給我們的語法檢查,怎樣保證代碼的質量呢?jshint 是一個強大的工具。
1. 概要說明
官方地址:http://jshint.com/
GitHub 地址:https://github.com/jshint/jshint
JSHint 是一個使用 JavaScript 編寫的 JavaScript 的代碼質量檢查工具,主要用來檢查代碼質量以及找出一些潛在的代碼缺陷。
2. 下載 jshint
使用 NPM 下載一個 jshint 讓我們測試一下。
npm install grunt-contrib-jshint --save-dev
看到如下的輸出
PS C:\Study\framework> npm install grunt-contrib-jshint --save-dev
npm WARN peerDependencies The peer dependency grunt@>=0.4.0 included from grunt-contrib-jshint will no npm WARN peerDependencies longer be automatically installed to fulfill the peerDependency npm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly. grunt@0.4.5 node_modules\grunt ├── dateformat@1.0.2-1.2.3 ├── which@1.0.9 ├── eventemitter2@0.4.14 ├── getobject@0.1.0 ├── colors@0.6.2 ├── rimraf@2.2.8 ├── async@0.1.22 ├── hooker@0.2.3 ├── grunt-legacy-util@0.2.0 ├── exit@0.1.2 ├── minimatch@0.2.14 (sigmund@1.0.1, lru-cache@2.6.5) ├── lodash@0.9.2 ├── coffee-script@1.3.3 ├── underscore.string@2.2.1 ├── iconv-lite@0.2.11 ├── nopt@1.0.10 (abbrev@1.0.7) ├── findup-sync@0.1.3 (glob@3.2.11, lodash@2.4.2) ├── grunt-legacy-log@0.1.2 (grunt-legacy-log-utils@0.1.1, lodash@2.4.2, underscore.string@2.3.3) ├── glob@3.1.21 (inherits@1.0.2, graceful-fs@1.2.3) └── js-yaml@2.0.5 (esprima@1.0.4, argparse@0.1.16) grunt-contrib-jshint@0.11.2 node_modules\grunt-contrib-jshint ├── hooker@0.2.3 └── jshint@2.8.0 (strip-json-comments@1.0.4, exit@0.1.2, shelljs@0.3.0, console-browserify@1.1.0, minimatch@2.0.10, cli@ 0.6.6, lodash@3.7.0, htmlparser2@3.8.3)
重新查看 package.json ,可以看到已經添加了 jshint 的依賴說明。
{
"name": "framework", "version": "1.0.0", "description": "", "main": "index.js", "dependencies": { "grunt": "^0.4.5", "grunt-contrib-jshint": "^0.11.2" }, "devDependencies": { "grunt-contrib-jshint": "^0.11.2" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" }
3. 在 grunt 中配置 jshint 測試 javascrpt 腳本
在我們的項目文件夾根目錄中,創建一個前端項目源碼的文件夾 app,在其中創建一個 scripts 的文件夾,用來保存我們編寫的腳本。
創建名為 app.js 的腳本文件,寫入如下內容。
// Hello. // // This is JSHint, a tool that helps to detect errors and potential // problems in your JavaScript code. // // To start, simply enter some JavaScript anywhere on this page. Your // report will appear on the right side. // // Additionally, you can toggle specific options in the Configure // menu. function main() { return 'Hello, World!'; } main();
我們需要在 grunt 中配置 jshint 的任務。
module.exports = function(grunt) { // Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), // Make sure code styles are up to par and there are no obvious mistakes // code style check // 代碼檢查 jshint: { all: [ 'app/**/*.js' ], options: { browser: true, // browser environment devel: true // } } }); grunt.loadNpmTasks('grunt-contrib-jshint'); };
all 中配置需要檢查的腳本文件路徑,options 中的 browser 用來配置說,我們的腳本需要在瀏覽器環境下執行,這樣,我們的腳本中可以使用 console、setTimeout 等等函數了。
現在執行 grunt hint 就可以看到如下的輸出。
PS C:\Study\framework> grunt jshint Running "jshint:all" (jshint) task >> 1 file lint free. Done, without errors.
如果把腳本中 main() 后面的分號 (;) 刪除掉,重新檢查,就會發現 jshint 發揮了作用。它告訴我們 app.js 文件的第 16 行 main() 后面少了一個分號 (;)
PS C:\Study\framework> grunt jshint Running "jshint:all" (jshint) task app/scripts/app.js 16 |main() ^ Missing semicolon. >> 1 error in 1 file Warning: Task "jshint:all" failed. Use --force to continue. Aborted due to warnings.
4. 配合 jQuery
在使用 jQuery 腳本庫的情況下,我們的函數可能是這樣的,使用 jQeury 的 ready 函數來開始。
"use strict"; $( function(){ console.info('Hello, world.'); });
這時使用 jshint 檢查,就會發現 $ 是一個問題。
PS C:\Study\framework> grunt jshint Running "jshint:all" (jshint) task app/scripts/app.js 1 |'use strict'; ^ Use the function form of "use strict". 3 |$( function(){ ^ '$' is not defined. >> 2 errors in 1 file Warning: Task "jshint:all" failed. Use --force to continue. Aborted due to warnings.
第一個錯誤是 jshint 的規則 strict mode directive in the outermost scope of the code 導致,我們應該將 "use strict"; 放在函數內部的第一行中。
具體的原因說明:http://jslinterrors.com/use-the-function-form-of-use-strict
第二個錯誤是說,jshint 提示說不認識 $,'$' is not defined.
jQuery 是在另外的庫中定義的,我們這里只是使用而已。可以配置 jshint 中配置 $ 是一個全局變量。
腳本修改為:
$( function(){ "use strict"; console.info('Hello, world.'); });
Gruntfile.js 修改為
module.exports = function(grunt) { // Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), // Make sure code styles are up to par and there are no obvious mistakes // code style check // 代碼檢查 jshint: { all: [ 'app/**/*.js' ], options: { globals: { $: false, jQuery: false }, browser: true, // browser environment devel: true // } } }); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.registerTask('default', 'Hello, world task description.', function() { grunt.log.writeln('Hello, world.'); }); };
5. Options
任何配置選項都會被透明底傳遞給 JSHint, 所以,你可以配置 JSHint 支持的任何特性。支持的特性見 JSHint documentation .
這里還額外支持一些特性:
globals
Type: Object
Default: null
定義全局變量的字典,Key 就是全局變量的名字,布爾型的值用來表示可賦值。這不是 JSHint 的標准選項,但是會作為第三個參數傳遞給 JSHint。
jshintrc
Type: String or true
Default: null
如果設置為 true,這里的配置參數不會傳遞給 JSHint,JSHint 將會通過 .jshintrc 文件來獲取參數。
如果設置了文件名,將會通過這個文件獲取配置參數. 這個 jshintrc 文件必須是一個合法的 JSON 文件,類似這樣。
{ "curly": true, "eqnull": true, "eqeqeq": true, "undef": true, "globals": { "jQuery": true } }
需要注意的是 jshintrc 文件的配置信息不會與 gruntfile.js 中的配置進行合並。
extensions
Type: String
Default: ''
需要檢查的非 dot-js 擴展名列表。
ignores
Type: Array
Default: null
需要忽略的文件和目錄列表. 將會覆蓋 .jshintignore 文件。
force
Type: Boolean
Default: false
設置為 true 將會報告 JSHint 錯誤,而不會將任務失敗掉。
reporter
Type: String
Default: null
Allows you to modify this plugins output. By default it will use a built-in Grunt reporter. Set the path to your own custom reporter or to one of the built-in JSHint reporters: jslint or checkstyle.
允許修改輸出插件,默認使用 Grunt 內置的報告器. 可以配置為自定義的報告器路徑,或者 JSHint 內置的報告器之一: jslint 或者 checkstyle。
See also: Writing your own JSHint reporter.
可以指定一個外部的報告器,例如: jshint-stylish:
首先通過 npm 進行安裝。
$ npm install --save-dev jshint-stylish
然后進行配置
options: { reporter: require('jshint-stylish') }
reporterOutput
Type: String
Default: null
配置報告的輸出路徑. 如果配置,輸出將不會輸出到標准輸出流,而是這個設置的路徑。
示例
Wildcards
In this example, running grunt jshint:all (or grunt jshint because jshint is a multi task) will lint the project's Gruntfile as well as all JavaScript files in the lib and test directories and their subdirectorieses, using the default JSHint options.
下面的這個例子,執行 grunt jshint:all ( 由於 jshint 是一個多任務的任務,可以直接使用 grunt jshint, ) 將會使用默認的 JSHint 配置。檢查 Gruntfile.js,lib 下面的任何 js 文件,test 下面的任何 js 文件,
// Project configuration. grunt.initConfig({ jshint: { all: ['Gruntfile.js', 'lib/**/*.js', 'test/**/*.js'] } });
Linting before and after concatenating
下面的這個例子中,執行 grunt jshint 將會檢查 'beforeconcat' 和 'afterconcat' 的所有文件,這並不理想,因為 dist/output.js 會在 grunt-contrib-concat plugin 的 concat 任務創建它之前被檢查。
在這種情況下,應該先檢查 'beforeconcat' 中的文件, 然后合並文件,最后再檢查 'afterconcat' 中的文件,這樣執行:grunt jshint:beforeconcat concat jshint:afterconcat.
// Project configuration. grunt.initConfig({ concat: { dist: { src: ['src/foo.js', 'src/bar.js'], dest: 'dist/output.js' } }, jshint: { beforeconcat: ['src/foo.js', 'src/bar.js'], afterconcat: ['dist/output.js'] } });
Specifying JSHint options and globals
這個例子演示了定制 JSHint 的配置. 注意在 grunt jshint:uses_defaults 執行的時候,將會使用默認的配置, 但是當 grunt jshint:with_overrides 執行的時候,將使用合並之后的配置。
// Project configuration. grunt.initConfig({ jshint: { options: { curly: true, eqeqeq: true, eqnull: true, browser: true, globals: { jQuery: true }, }, uses_defaults: ['dir1/**/*.js', 'dir2/**/*.js'], with_overrides: { options: { curly: false, undef: true, }, files: { src: ['dir3/**/*.js', 'dir4/**/*.js'] }, } }, });
Ignoring specific warnings
如果希望忽略特定的警告:
[L24:C9] W015: Expected '}' to have an indentation at 11 instead at 9.
可以通過在警告標識之前加上減號 (-) 來關掉它。
grunt.initConfig({ jshint: { ignore_warning: { options: { '-W015': true, }, src: ['**/*.js'], }, }, });

