惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
SegmentFault 最新的问题
A
About on SuperTechFans
NISL@THU
NISL@THU
V
Visual Studio Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
B
Blog RSS Feed
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI
美团技术团队
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Google DeepMind News
Google DeepMind News
小众软件
小众软件
博客园 - Franky
罗磊的独立博客
The Cloudflare Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
酷 壳 – CoolShell
酷 壳 – CoolShell
量子位
Hugging Face - Blog
Hugging Face - Blog
云风的 BLOG
云风的 BLOG
MongoDB | Blog
MongoDB | Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
B
Blog
The GitHub Blog
The GitHub Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
P
Proofpoint News Feed
有赞技术团队
有赞技术团队
Hacker News - Newest:
Hacker News - Newest: "LLM"
Cyberwarzone
Cyberwarzone
C
CXSECURITY Database RSS Feed - CXSecurity.com
Project Zero
Project Zero
Security Latest
Security Latest
L
Lohrmann on Cybersecurity
AWS News Blog
AWS News Blog
The Hacker News
The Hacker News
I
Intezer
J
Java Code Geeks
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
P
Privacy International News Feed
月光博客
月光博客
A
Arctic Wolf
Apple Machine Learning Research
Apple Machine Learning Research
D
Darknet – Hacking Tools, Hacker News & Cyber Security
博客园_首页
WordPress大学
WordPress大学
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Tor Project blog
博客园 - 三生石上(FineUI控件)
The Last Watchdog
The Last Watchdog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org

囧克斯

奔四了,写给40岁的自己 有序退网 我和 Vue.js 的十年 我参与《代码之外 Beyond Code》的故事 博客站迁移至 VitePress 的备忘 写给我的奶奶 中文格式化小工具 zhlint 及其开发心得 vue-mark-display:用 markdown 语法轻松撰写幻灯片 我对技术会议的一些看法 VueConf Hangzhou 见闻 第四届 CSSConf CN 见闻 [译]Web 表单的未来 [译]苹果正在做一些他们的程序员明摆着不想要的东西 [译]为什么我不会无偿加班且你也不应该 [译]如果管理是唯一可走的路,那就完蛋了 [译]如何撰写 Git 提交信息 [译]C 程序的原则 Vue 2.0 来了! Weex 近 4 个月的开源之路 Weex 在 JS Runtime 内的多实例管理 我理解的 SPA 我理解的 Flux 架构 【整理】Vue 2.0 自 beta 1 到 beta 4 以来的主要更新 通过一张图走进 Vue 2.0 Code Review for Vue 2.0 Preview Vue 2.0 发布啦! 务实的小而美 Vue.js 1.0.0 发布了! [译]如何成为一名卓越的前端工程师 手机淘宝前端的图片相关工作流程梳理 [译]如何让办公室政治最小化 Vue.js 源码学习笔记 从原型到发布——“团队时间线” 1.0 开发心得 Vue + webpack 项目实践 用 Koa 写服务体验 webcomponents 笔记 之 配置管理 小秀个人的13~14年摄影作品 (共19张) 由今年D2前端论坛想到的 [译]CSS命名神马的真心难 [译]Git 分支的最佳实践 [译]撰写可测试的 JavaScript [译]语义化版本管理 [译]通过HTML5 Canvas API调节图像的亮度和颜色 [译]JavaScript V8性能小贴士 [译]视觉差,走起! [译]Chrome开发者工具中评估性能的五大新特性 精气神儿 细节无微不至,彩屏让人又爱又恨——新老“神机”大对决:Nokia 1050 vs Nokia 1202 秦升拿到红牌之后…… 用Sass重新整理自己的博客主题样式 Connect中间件使用手册 巧用 RequireJS Optimizer 给传统的前端项目打包 编辑器小调查结果 烟火——写给蛇年的傲游和我 小秀个人的全年摄影作品 (共15张) 2012年终毫无正能量的总结 标签?ID?还是CLASS? 微创新=伪创新 HTML5峰会归来 分享bookmarklet一则:随意阅读 国际羽联和中国队之间的恶性循环 ZeroClipboard 学习笔记 “思考人生” 听杨东杰弹吉他 学习精髓 网站装修笔记20120426 网站装修笔记20120414 网站装修笔记20120406 分享Typecho插件:百度统计助手 我的得奖感言 网站装修笔记20120331 用CSS3制作尖角标签按钮样式 分享Typecho插件:Markdown 解析器 + 编辑器 分享Typecho皮肤:我的字很大 汇总自己过去的一些HTML5科普文章 html5中的消息通信简介 + 我的新网站开张 网站装修计划 Typed Arrays 是神马? 文明看球 HTML5中的文件处理 之 File Writer API HTML5中的文件处理 之 File API 独生子女、互相等和不耐烦 IndexedDB技术简介(四) IndexedDB技术简介(三) IndexedDB技术简介(二) IndexedDB技术简介(一) 把博客的字体进一步调大,同时去掉了侧边栏 “模仿别人是为了找到自己” 写给我未婚妻的2011年 写给自己的2011年 手把手教你入门EaselJS做HTML5动画 “吃了吧,不吃就浪费了” 写给傲游的2011年 所谓专业 写给HTML5的2011年 对HTML5中LocalStorage的一些使用建议 回味一下我2011年看到的最过瘾的5场足球比赛 浅浅浅谈开饭店被顾客吃出“异物”的用户体验 前端的本职 继续对Mac穷追猛打 之 修改原生按钮文字大小的技巧
[译]JSLint 文档
勾三股四 · 2013-02-17 · via 囧克斯

译自:https://www.jslint.com/lint.html

什么是JSLint? ​

JSLint 是一个用来查找各种 JavaScript 程序中的问题的 JavaScript 程序。它是一个代码之类工具。

早些年C 语言中,有些程序的常见错误是主流的编译器无法抓住的。所以出现了一个名叫 lint 的附带程序,可以通过搜索源文件寻找错误。

随着语言的成熟,其定义的健壮性足以消除一些不安因素,编译器也在问题警告方面越做越好,lint 也不再需要了。

JavaScript 是一个年轻的语言。它原本只是用在网页上完成一些无需劳驾 Java 的小任务。但 JavaScript 是一个强大得惊人的语言,现在它已经在大项目中派上用场了。当项目变得复杂之后,之前从易用角度出发的语言特性就带来了一些麻烦。这是一个为 JavaScript 而生的 lint 呼之欲出:它就是 JSLint,一个检查 JavaScript 语法、判断 JavaScript 语法有效性的工具。

JSLint 会拿来一段 JavaScript 源代码并对其进行检索。一旦发现问题,它就会返回一则消息,用来描述这个问题以及源代码中的大概位置。发现的问题不一定是,但通常是语法上的错误。JSLint 通过一些代码规范来杜绝结构性的问题。这并不证明你的程序是正确的,只是提供另一种发现问题的眼光。

JSLint 定义了一个专业的 JavaScript 的子集,它比 ECMAScript 标准第三版的定义更严格,和 JavaScript 编码规范中的建议相对应。

JavaScript 是一个粗中有细的语言,它比你想象中的更好。JSLint 帮助你回避很多问题,在这个更好的语言中撰写程序。JSLint 会拒绝一些浏览器支持的程序,因为浏览器并不关心代码的质量。你应该接受 JSLint 的所有建议。

JSLint 在 JavaScript 源代码、HTML 源代码、CSS 源代码或 JSON 文本中都可以运行。


全局变量 ​

JavaScript 的最大问题就是其依赖的全局变量,特别隐含的全局变量。如果一个变量没有被显性的声明 (通常是通过 var 语句),则 JavaScript 会假定这个变量是全局变量。这会掩盖拼写错误等其它问题。

JSLint 希望所有的变量和函数都要在使用或调用之前被声明。这样我们就可以探测隐含着的全局变量。同时,这也让程序的可读性增强了。

有的时候一个文件会依赖于在别处定义好的全局变量或全局函数。这时你可以通过一个 var 语句让 JSLint 识别该程序依赖的这些全局函数和对象。

一个全局声明大概如下所示:

var getElementByAttribute, breakCycles, hanoi;

该声明应该出现在靠近文件最上方的位置,且必须出现在使用这些变量之前。

同时,我们有必要在一个变量被赋值之前通过 var 语句对其进行声明。

JSLint 同样可以识别一段 /*global*/ 指令,该指令可以为 JSLint 注明在该文件中使用但在其它文件中定义好的变量。该指令可以包含一串变量名,用逗号隔开。每个名字可以跟随一个可选的冒号以及 truefalsetrue 表示该变量可以被该文件赋值,而 false 则表示该变量不能被赋值 (这是默认行为)。在函数作用域也是如此。

有些全局变量可以被你预定义。选择假设为浏览器 (browser) 选项可以预定义浏览器提供的标准的全局属性,比如 documentaddEventListener。它等同于:

/*global clearInterval: false, clearTimeout: false, document: false, event: false, frames: false, history: false, Image: false, location: false, name: false, navigator: false, Option: false, parent: false, screen: false, setInterval: false, setTimeout: false, window: false, XMLHttpRequest: false */

选择假设为 Node.js (node) 选项可以预定义 Node.js 环境下的全局变量。它等同于:

/*global Buffer: false, clearInterval: false, clearTimeout: false, console: false, exports: false, global: false, module: false, process: false, querystring: false, require: false, setInterval: false, setTimeout: false, __filename: false, __dirname: false */

选择假设为 Rhino (rhino) 选项可以预定义 Rhino 环境下的全局属性。它等同于:

/*global defineClass: false, deserialize: false, gc: false, help: false, load: false, loadClass: false, print: false, quit: false, readFile: false, readUrl: false, runCommand: false, seal: false, serialize: false, spawn: false, sync: false, toint32: false, version: false */

选择假设为 Windows (windows) 选项可以预定义 Microsoft Windows 提供的全局属性。它等同于:

/*global ActiveXObject: false, CScript: false, Debug: false, Enumerator: false, System: false, VBArray: false, WScript: false, WSH: false */

分号 ​

JavaScript 使用近似于 C 语言的语法,它要求使用分号来分割确定的语句。JavaScript 试图通过一个自动插入分号的机制让这些分号变得可有可无。这是比较危险的,因为它可以掩盖你的错误。

和 C 一样,JavaScript 有 ++--( 操作符,这些操作符可以作为前缀或后缀。分号可以用来消除这里的二义性。

在 JavaScript 中,一个折行可以是一个空格,也可以当做分号使用,两者容易产生混淆。

JSLint 希望除了 forfunctionifswitchtrywhile,每个语句都以 ; 结尾。同时 JSLint 不希望看到没有必要的分号或空白语句。

逗号 ​

我们可以用逗号操作符写出极度巧妙的表达式。同时也可以掩盖一些程序上的错误。

JSLint 希望逗号只用来当做分隔符,而不是操作符 (for 语句中的初始化部分和自增部分除外)。数组直接量里不希望有被省略的元素,多余的逗号不应该被使用,逗号不应该出现在数组直接量或对象直接量的最后一个元素的后面,因为一些浏览器无法正常识别。

作用域 ​

在很多语言中,每个块都产生一个作用域,块内产生的变量在块外是看不到的。

在 JavaScript 中,块并不产生新的作用域,只有函数作用域。在一个函数中任意位置声明的变量都在整个函数中可见。JavaScript 的块混淆了有经验的程序员,并导致了错误的出现,因为用相似的语法做了一个错误的承诺。

JSLint 希望 functionifswitchwhilefordotry 语句之外不要产生其它块。

在有块级作用域的语言里,通常都推荐变量声明在第一次使用的地方。但是因为 JavaScript 没有块级作用域,所以明智的选择就是在函数的最顶端声明所有的函数变量。这里推荐每个函数用单一的一个 var 语句完成变量声明。这个要求可以通过 vars 选项取消掉。

必要的块 ​

JSLint 希望 ifwhiledofor 语句都由块生成,{ 也就是说,语句是被大括号包住的 }

JavaScript 允许一个 if 语句这样书写:

if (condition) statement;

这个格式是公认的:当很多程序员都基于相同的代码工作时,会给整个项目带来很多错误。这也是为什么 JSLint 希望如下使用块:

if (condition) { statement; }

经验告诉我们这个格式更保险一些。

表达式语句 ​

我们希望一个表达式语句是一个赋值或一个函数/方法调用或 delete。其它表达式语句都可能导致错误。

for in

for in 语句允许在一个对象的所有属性名内进行循环。不幸的是,这样的循环也会覆盖到其原型链中所有被继承而来的属性。其副作用就是当我们只关心数据的时候,它连方法函数也会处理一遍。如果此时该程序没有任何预防措施,那么就会导致失败。

每个 for in 语句的主体部分都应该包裹一个起过滤效果的 if 语句。该语句可以选择特殊类型或范围的值、或排除函数类型的属性、或排除原型的属性。比如:

for (name in object) { if (object.hasOwnProperty(name)) { .... } }

switch

一个 switch 语句中常见的错误就是忘记在每个条件的结尾写上 break 语句,导致程序没有及时跳走。JSLint 希望语句的下一个 case 之前或 default 之前必须有下面三个当中的一个:breakreturnthrow

var

JavaScript 允许 var 在一个函数内的任何位置完成定义。JSLint 的要求则会更严格一些。

JSLint 希望一个 var 只被声明一次,并且是在使用之前被声明。

JSLint 希望一个 function 在使用之前被声明。

JSLint 希望函数的参数不要被声明为变量。

JSLint 不希望 arguments 数组被声明为 var

JSLint 不希望一个变量被定义在块中。这是因为 JavaScript 的块并不具有块级作用域。这会造成意料之外的结果。把所有的变量都定义在函数的最顶部。

with

with 语句的初衷是提供一个访问对象嵌套属性的简写方式。不幸的是,当我们设置新属性时这个行为非常糟糕。永远不要使用 with 语句。请用一个 var 替代之。

=

JSLint 不希望看到 ifforwhiledo 语句的条件判断中出现赋值语句。这是因为似乎:

if (a = b) { ... }

的本意是:

if (a == b) { ... }

当我们难以从常用语句中察觉出明显的错误时,是很难把程序写对的。

==!=

==!= 操作会在比较之前做类型转换。这是不提倡的,因为它导致 ' \t\r\n' == 0 的结果是 true。这会掩盖一些类型错误。JSLint 无法依赖 == 进行判断,所以最好别再使用 ==!= 了,以后都用更可靠的 ===!== 操作替代之。

如果你只是在乎一个值是真的还是假的,那么可以使用简写方式,比如把:

(foo != 0)

替换为:

(foo)

而将:

(foo == 0)

替换为:

(!foo)

我们有一个 eqeq 选项,允许使用 ==!=

标签 (labels) ​

JavaScript 允许任何语句拥有标签,标签拥有各自的命名空间。JSLint 的要求会更严格。

JSLint 希望标签只出现在响应 breakswtichwhiledofor 的语句上。JSLint 希望标签可以同变量和参数区分开来。

无法到达的代码 ​

JSLint 希望一个 returnbreakcontinuethrow 语句后面都会跟着一个 }casedefault

混乱的加号减号 ​

JSLint 希望 + 不会紧跟着 +++,而 - 不会紧跟着 ---。少写一个空格就会把 + + 变成 ++,这种错误是很难被发现的。为了避免混乱,请善用括号。

++--

自增操作符 ++ 和自减操作符 -- 是公认的会鼓励过度使用技巧而导致糟糕的代码。它们是导致病毒和安全威胁的错误构建。同样的,乱用前自增和后自增会产生 off-by-one 的错误,排查这样的错误是极为困难的。我们有一个 plusplus 选项来允许使用这些操作符。

位操作符 ​

JavaScript 没有整数类型 (*),但是其具备位操作符。位操作符会先把操作对象由浮点数转换回整数,所以这样的位操作效率远不及 C 或其它语言。位操作符极少用在浏览器应用里。与逻辑操作符的相似性也会掩盖一些程序的错误。bitwise 选项允许使用 <<>>>>>~&| 这些操作符。

eval 是魔鬼 ​

eval 函数 (及其相似的 FunctionsetTimeoutsetInterval) 提供了 JavaScript 编译器的访问形式。这在一些情况下是有必要的,但是在大多数情况下它代表了相当糟糕的代码。eval 函数是 JavaScript 最不应该被使用的特性。

void

在大多数近似于 C 的语言中,void 是一个类型。在 JavaScript 中,void 是一个前缀操作符,它总是返回 undefinedJSLint 不希望看到 void 因为它具有迷惑性且没有实质的用处。

正则表达式 ​

正则表达式写起来既简洁又神秘。JSLint 会检测一些可能导致可移植性问题的问题。同时会推荐把具有视觉混淆性质的字符全部转义。

JavaScript 语法中,正则表达式直接量会多写一对 / 字符。为了避免混淆,JSLint 希望一个正则表达式字面量的开头是一个 (=:, 字符。

构造函数和 new

构造函数是设计为通过 new 前缀使用的函数。new 前缀基于函数的 prototype 创建一个新的对象,并把函数隐性提供的 this 参数绑定到那个对象。如果你忽略了 new 前缀的使用,则不会有新的对象被创建,而 this 则会绑定到全局对象上。这是非常严重的错误

JSLint 强制规范构造函数的函数名大写开头。JSLint不希望看到一个函数调用的函数名是大写开头但没有 new 前缀。JSLint 也不希望看到 new 前缀用在一个函数名不是大写开头的函数上。这一要求可以通过 newcap 选项关掉。

JSLint 不希望看到 new Numbernew Stringnew Boolean 的包裹形式。

JSLint 不希望看到 new Object,用 {} 替换之。

JSLint 不希望看到 new Array,用 [] 替换之。

属性 ​

因为 JavaScript 是个弱类型动态对象语言,所以不太可能在编译的时候判定一个属性名是否拼写正确。JSLint 在这方面提供了一些帮助。

在其报告的最底端,JSLint 显示了一个 /*properties*/ 指令。它包含了一些名称和字符串直接量,它们是所有使用过的点标记、下标标记和对象直接量中用来命名对象属性的。你可以查阅这个列表来找到拼错的词。这是个比较简单的办法。

你还可以复制 /*properties*/ 指令到你的脚本文件的顶端。JSLint 会根据这个列表检查所有的属性名。这样,你就可以使用 JSLint 检查拼写错误了。

比如:

/*properties charAt, slice */

不安全字符 ​

有一些字符是不同的浏览器显示起来不一致的,在放入字符串之前必须先转义。

\u0000-\u001f \u007f-\u009f \u00ad \u0600-\u0604 \u070f \u17b4 \u17b5 \u200c-\u200f \u2028-\u202f \u2060-\u206f \ufeff \ufff0-\uffff

不检查的内容 ​

JSLint 不会做流程分析,也不会判断变量在使用之前是否已经被赋值。这是因为变量都有默认值 (undefined),很多应用本身就是这样处理的。

JSLint 不会做任何类型的全局分析,不会尝试判断伴随 new 使用的函数是真正的构造函数 (只是遵循大小写规范),不会检查属性名拼写是否正确 (只是针对 /*properties*/ 指令进行匹配)。

HTML ​

JSLint 可以处理 HTML 文本。它可以找到包含在 <script> ... </script> 标签中的 JavaScript 内容。也可以通过 JavaScript 找到 HTML 内容中公认的问题:

  • 所有的标签必须小写。
  • 所有的标签必须闭合 (比如 </p>)。
  • 所有的标签必须正确的嵌套
  • 必须用实体 &lt; 表示字面量 >

JSLint 比 XHTML 的要求要低,但是比主流浏览器的要求要严格。

JSLint 也会检查 '</' 在字符串字面量的出现情况,你应该用 '<\/' 替换之。额外的反斜杠会被 JavaScript 编译器忽略掉,但 HTML 解析器不会。类似的技巧都不是必要的,但就是这样。

这里有一个 fragment 选项,用来检查一个合格的 HTML 片段。如果 adsafe 选项也选用,则片段必须是一个遵守 ADSafe widget 规则的 <div>

CSS ​

JSLint 可以检查 CSS 文件。它检查 CSS 文件的第一行是不是:

@charset "UTF-8";

这个特性是试验性的。请把任何问题或束缚报告出来。这里有一个 css 选项,可以容忍一些非标准的使用习惯。

选项 ​

JSLint 提供了很多选项,它们控制了其操作和敏感度。在网页版中,选项是可以通过复选框进行勾选的。

我们还提供了通过构造 /*jslint*/ 指令和 /*properties*/ 指令的方式进行辅助。

JSLint 被当做函数调用时,它接受一个 option 对象参数,这个参数允许你判定你可接受的 JavaScript 子集。网页版的 JSLinthttps://www.JSLint.com,就是这样工作的。

选项还可以在 /*jslint*/ 指令中被定义:

/*jslint nomen: true, debug: true, evil: false, vars: true*/

选项指令起始于 '/*jslint'。注意 j 前面没有空格。本规范包含了一系列的键值对,这些键是 JSLint 的选项,值是 truefalseindent 选项可以取一个数字。一个 /*jslint*/ 指令优先于 option 对象。指令遵照函数作用域。

(表格略,详见:https://www.jslint.com/lint.html#options)

报告 ​

如果 JSLint 可以完成检查,那么它会生成一个函数报告。其列出下面每个函数:

  • 起始行号。
  • 名称。如果是匿名函数,JSLint 会“猜”出这个名称。
  • 参数。
  • Closure:被声明的变量和参数之中,被子函数使用的部分。
  • Variables:被声明并只在该函数中使用的变量。
  • Exceptions:被 try 语句声明的变量。
  • Unused:被声明但从未在该函数中使用的变量。这可能意味着一个错误。
  • Outer:被其它函数声明且在该函数中使用的变量。
  • Global:在该函数中使用的全局变量。把这个用量降到最少。
  • Label:该函数中使用的语句标记。

报告还会包含一个使用过的属性名列表。这里是JSLint的消息列表