三分钟从零单排js静态检查

1,143 阅读6分钟

什么是静态检查

距离上次写三分钟从零单排(三分钟从零单排gulp-less配置) 的文章过去好久了,这次来聊一聊静态检查。

因为现在正在带学生的js基础课,开始写一些整体项目了。日常遇到很多关于缺少括号,多写了一个点,变量没有声明诸如此类的错误。

而且在编程界一直有一个神秘的现象,就是越简单的bug就越难找到。那种死都改不好的bug基本都是一眼就看的出来,一个小时都找不到的错误,八成是一下子就改好的。从上学的时候就发现了这个规律,所以一旦找了很长时间都找不到bug在哪,赶紧把自己切换到白痴模式,很快就能找到错误。

但是对于新人来说,每天都会犯很多语法细节的错误,并且在其中浪费大量的时间。有很多时候,明明只是一个括号匹配的小问题,结果为了找出来问题就反复修改调试了好几处代码,最后反而把好用的代码改坏了,人也很烦躁,觉得很有挫败感。

当然,静态检查不仅仅是帮助初学者进行学习,对于我们日常工作来说,避免一些小错误也是很有效的。另一个重要的用途是,保持团队的代码风格一致,使得提交git的时候可以避免很多不必要的修改行出现。

所以无论是从学习的角度,还是从团队开发的角度来说,静态代码检查都可以有效的提高开发效率。

Sublime插件

因为我的日常使用Sublime作为开发工具,所以用Sublime的使用举例说明。

首先要安装两个插件:

SublimeLinterSublimeLinter-contrib-eslint
SublimeLinter 是一个可以支持sublime使用各种静态检查工具的工具,可以配置触发条件,显示样式,以及使用什么工具做静态检查。

什么,你问我怎么安装插件?

1、通过快捷键 ctrl+` 或者 View > Show Console 菜单打开控制台

2、粘贴对应版本的代码后回车安装

适用于 Sublime Text 3:

import urllib.request,os;pf='Package Control.sublime-package';ipp=sublime.installed_packages_path();urllib.request.install_opener(urllib.request.build_opener(urllib.request.ProxyHandler()));open(os.path.join(ipp,pf),'wb').write(urllib.request.urlopen('http://sublime.wbond.net/'+pf.replace(' ','%20')).read())

适用于 Sublime Text 2:

import urllib2,os;pf='Package Control.sublime-package';ipp=sublime.installed_packages_path();os.makedirs(ipp)ifnotos.path.exists(ipp)elseNone;urllib2.install_opener(urllib2.build_opener(urllib2.ProxyHandler()));open(os.path.join(ipp,pf),'wb').write(urllib2.urlopen('http://sublime.wbond.net/'+pf.replace(' ','%20')).read());print('Please restart Sublime Text to finish installation')

当安装好SublimeLinter之后,就可以在Tools > SublimeLinter看到插件的配置项了。

包括检测模式,报错信息样式,切换检测器等各种配置。所有的配置通过打开Open User Settings都可以看到。


因为现在还没有任何的检测器,所以还无法工作。

可选用的静态检测的工具有eslint jshint jslint JSCS等。

JSLint

JSLint是其中最老的工具。在2002年 Douglas Crockford开发了该工具,根据其经验,强制使用js语言中精粹的部分。如果你同意这些精粹,JSLint能成为一个好的工具。

JSLint的缺点是不能配置和拓展。你根本不能禁掉需要特性,并且很多缺少文档。官方文档非常不友好,例如缺少如何将其集成到编辑的信息。

JSHint

作为一个可配置的JSLint版本,JSHint被开发出来。你可以配置每个规则,将其放到一个配置文件中,这样在大项目中可以容易使用。JSHint对每个规则有好的文档,所以可以准确知道每个规则的作用。将其集成到编辑器也是简单的。

ESLint

ESLint是最新出来的工具。它被设计的容易拓展、拥有大量的自定义规则、容易的通过插件来安装。它给出准确的输出,而且包括规则名,这样可以知道哪个规则造成了错误。

横向对比之后,我们选择用ESLint作为静态检测的工具,于是我们还需要插件:Sublime-contrib-eslint

这时候打开 Tools > SublimeLinter > Open User Settings 可以看到,linters配置项已经有了eslint

所以看起来好像已经可以了呢,赶紧迫不及待的打开一个js文件,结果却什么都没有显示,我们用ctrl+`打开控制台看一下,发现有报错

原来是eslint没有安装,需要手动安装eslint包,打开cmd,输入:

npm i eslint -g

全局安装eslint之后重启一下SublimeLinter,结果发现,妈的还是不好使……

再次使用ctrl+`打开控制台,这次说明错误的原因是没有eslint的配置文件。

ESlint 被设计为是完全可配置的,这意味着你可以关闭每一个规则,只运行基本语法验证,或混合和匹配绑定的规则和自定义规则,以让 ESLint 更适合于你的项目。有两种主要的方式来配置 ESLint:

Configuration Comments - 使用 JavaScript 注释把配置信息直接嵌入到一个文件

Configuration Files - 使用 JavaScript、JSON 或者 YAML 文件为整个目录和它的子目录指定配置信息。可以用 .eslintrc.* 文件或者在 package.json文件里的 eslintConfig 字段这两种方式进行配置,ESLint 会查找和自动读取它们,再者,你可以在命令行指定一个配置文件。
其实对于SublimeLinter来说,还有一种一劳永逸的方法,就是把配置文件写在插件设置中

"linters": {
            "eslint": {
                "@disable": false,
                "args": [
                    "--config",
                    "${sublime}/user/eslint.conf"
                ],
                "excludes": []
            }
        }

其中${sublime}/user/eslint.conf是配置文件的路径,${sublime}在我的电脑上路径是C:\Users\USERNAME\AppData\Roaming\Sublime Text 3\Packages

以下是我在使用的配置文件:

{
    "env": {
        "browser": true,
        "node": true,
        "es6": true
    },
    "globals": {
        "jest": true,
        "describe": true,
        "it": true,
        "expect": true,
        "$": true,
        "require": true,
        "define": true,
        "module": true,
        "MZ": true,
        "console": true,
        "window": true,
    },
    "rules": { //0 关闭,1 警告,2 错误
        "block-scoped-var": 0,                      //把 var 语句看作是在块级作用域范围之内
        "curly": 1,                                 //为所有控制语句指定花括号约定,警告
        "eol-last": 0,                              //强制文件最后一行为空行,关闭
        "eqeqeq": 1,                                //- 要求使用 === 和 !==
        "dot-notation": 2,                          //尽可能的使用点符号
        "no-console": 0,                            //不允许存在 console。关闭
        "no-empty": 1,                              //空的代码块
        "no-self-compare": 1,                       //禁止自身比较
        "no-shadow": 2,                             //定义的变量不允许已在外层作用域定义
        "no-undef": 2,                              //变量未定义
        "no-underscore-dangle": 0,                  //禁止标识符中有悬空下划线。关闭
        "no-unused-expressions": 1,                 //禁止在语句的位置使用表达式
        "no-unused-vars": [1, {"vars":"local"}],    //变量定义后未使用
        "space-infix-ops":2,                        //要求操作符周围有空格
        "no-use-before-define": 1,                  //不允许在变量定义之前使用它们
        "key-spacing":[1, {
            "singleLine": {
                "beforeColon": false,
                "afterColon": true
            },
            "multiLine": {
                "beforeColon": true,
                "afterColon": true,
                "align": "colon"
            }
        }],
        "no-multi-spaces": [1, {"exceptions": {
            "ImportDeclaration": true, 
            "AssignmentPattern": true, 
            "VariableDeclarator": true, 
            "Property": true} 
        }],
        "quotes": [1, "single", "avoid-escape"] //使用单引号
    },
    "extends": "eslint:recommended",
    "ecmaFeatures": {
        "jsx": true,
        "experimentalObjectRestSpread": true
    },
    "plugins": [
        "react"
    ]
}

更多规则可以在List of available rules查找配置

所有的规则默认都是禁用的。在配置文件中,使用 "extends": "eslint:recommended" 来启用推荐的规则,报告一些常见的问题,在下文中这些推荐的规则都带有一个绿色对勾标记。
命令行的 --fix 选项用来自动修复规则所报告的问题(目前,大部分是对空白的修复),在下文中会有一个黄色扳手的图标。

现在我们可以看到这个文件有三处运算符没有加空格,两处使用双引号的地方。

终于可以告别学生无休止的小白问题,有时间去看屁股,啊不,去看教案了……