用JSLint精炼提升JavaScript代码

由于移动应用的盛行和HTML5的广泛运用,JavaScript正越来越流行。JavaScript受欢迎的部分原因是因为它的灵活便捷,你可以快速上手,它不需要重量级的开发环境,也不需要第三方应用支持,只要你打开一个文本编辑器,然后保存,最后通过网页浏览器运行即可。

  但是,对于新手而言,使用JavaScript处处存在陷阱。在一段复杂的脚本中,JavaScript语言的延展性常常引起怪异的bug。例如,未声明的局部变量可能会不知不觉修改全局变量。

  现在,打开JSLint网站,正如其网站所言,它是“JavaScript代码质量工具”。JSLint的作者是Douglas Crockford,因其对JavaScript(ECMAScript)和JSON的贡献而著名。

  (译注:Douglas Crockford是 web领域技术权威之一,他是JSON、JSLint、JSMin和ADSafe的创造者,也是名著《JavaScript: The Good Parts》(中文版《JavaScript语言精粹 》)的作者。撰写了许多广为流传、影响深远的技术文章,包括“JavaScript:世界上最被误解的语言”。)

  JSLint帮助JavaScript程序员在编程过程中遵循一定的编码规范。JSLint是以基于严格模式(Strict Mode)为前提,参考第5版ECMAScript标准。与一般模式相比,严格模式下你的代码需要按照更严格的规则运行。

  (译注:对严格模式不了解的童鞋,可以参考这两篇文章《ECMAScript 5.1简介》《是时候使用JavaScript严谨模式(Strict Mode)提升团队开发效率》)

  使用JSLint

  我们来用JSLint运行一个示例。写一个简单的jQuery插件,通过prefix显示msg接收的信息,如果传给type的值为false则不显示prefix。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
(function ($) {
    $.fn.loading = function(msg, type, cssClass){
        var prefixes = {
            warning: 'Warning: ' + msg,
            error: 'Error: ' + msg,
            info: 'Info: ' + msg,
            warning: 'Caution: ' + msg,
        };
        if (type) {
            concatMsg = prefixes[type];
        } else {
            concatMsg = msg;
        }
        $(this).each(function()  {
            var tis = $(this)
            if (msg == false) {
                tis.html('');
            } else {
                tis.html(concatMsg);
            }
        });
     }
})(jQuery);

  尽管这段代码作为jQuery的插件运行还算正常,但当你用Firefox或Chrome运行时,会发现有几处明显的错误,以及一些不易察觉的问题。与其耗费脑力解决这些问题,不如通过JSLint来帮助我们。将上面这段代码拷贝至JSLint网站的文本框内,然后点击”JSLint”按钮,代码建议和错误提示会出现在下方。

  JSLint指出的第一个错误是:丢失“use strict”声明。这个错误表示该函数未在严格模式下执行。为纠正该错误,我们在函数主体的头部,添加“use strict”语句以启动严格模式。

1
'use strict';

  加入严格模式声明语句后,再次点击“JSLint”按钮,提示丢失“use strict”的错误信息将消失。现在,我们可以继续看下一个错误。接下来的这个错误是关于空格的问题,鉴于它不能算个真正的错误,我们可以放心地忽略它。

  你可以将页面最下方的“messy white space”选项改为true,这样你就可以保留function关键字后不留空格的写法。但是现在,我们保留“messy white space”选项的default属性,因为这个功能也会帮助我们检查其他空格问题,这个我们之后再说。

  同样需要注意的是,虽然JSLint指出的第二个和第三个错误指向同一行代码,但错误点并不一样。后者JSLint建议在右括号“)”和左大括号“{”之间空一格,现在我们纠正下这个错误。

  插入空格后,再次点击“JSLint”按钮,下一个错误出现在第8行,第39个字符处。prefixes对象包含了两个一模一样的warning属性,将第二个warning修改为caution。

  这次就不再点击“JSLint”按钮,直接看下一个错误吧。定义对象的代码块的最后多了一个逗号。像这类错误,Chrome和Firefox这些浏览器也许会忽略,但IE就不会那么友好了,所以我们把这个逗号移除掉。

  之后的两个错误指向未定义的变量concatMsg。如果一个变量在当前作用域中没有被定义,JavaScript就会全局查找看是否有在别处定义过。若这时你还引入了外部代码,并碰巧在全局中定义过该变量,那么一旦出错,你很有可能要抓破头皮,费尽心力地寻找bug原因。所幸有了JSLint,我们可以将这类错误扼杀在摇篮中。

  现在纠正这个错误,并重构代码。因为concatMsg的默认值为msg,所以我们可以将msg先赋给它,待需要时再修改。如下所示,关于concatMsg的代码为:

1
2
3
4
var concatMsg = msg;
if (type) {
    concatMsg = prefixes[type];
}

  继续往下,有一个与之前类似的空格问题,纠正它。紧接着,JSLint指出丢失了一个分号(如下图所示)。JSLint会假设没有分号结尾的命令行永远不会被终止。所以,当下面出现if时,JSLint认为这里应该有个分号。尽管根据语言规范,结束的分号可有可无,但是加上它是一个良好的习惯。因为这类不良代码在大项目协作中很容易引起莫名的bug。所以平常编码过程中,应顺手避免此类问题。

  接下来又是一个很好的错误例子。JavaScript中,有‘相等’(==)和严格的‘相等’(===)比较。在这段案例代码中,如果不采用严格‘相等’比较,那么不管msg为空字符串还是false值,if内都为true。所以,这里我们采用严格‘相等’比较。

  好了,让我们再次点击“JSLint”按钮吧。如下图所示,错误出现在第10行,JSLint认为合并变量声明也是一个良好的编码规范。尽管concatMsg变量的声明紧随prefixes之后,但JSLint认为用逗号隔开,在一个命令语句中完成变量声明更好。

  下一个错误则又是关于格式的问题。咋一看,不就是多空了一格嘛,实在是太鸡毛蒜皮了。但是,如果在大量的脚本中,这种缩进问题搞不好也会引起难以发现的bug。所以,为了代码的统一性,我们还是往前移一格吧。

  下一个问题又和之前遇到的类似,但形式不一样。JavaScript的函数也可归属为变量,所以和其他变量赋值语句一样,JSLint希望在末尾加个分号。

  最后,如下所示,有两个错误出现在最后一行。第一个问题,JSLint建议将闭括号移至jQuery之后,因为这样不会使闭包函数定义产生歧义。第二个问题,JSLint认为jQuery变量不存在。但事实上你可能在实际页面中已引入了jQuery文件,所以我们可以在页面最下面的文本框内输入“jQuery”来解决这个问题(译者:JSLint Directive上面的文本框)。

  再次运行JSLint,它提示该函数需要接收三个参数。但是在本示例中,我们从未使用过第三个参数。因此,此处我们有两种方法解决这个问题。第一种,删除第三个参数。第二种,将下方的“unused parameters”项改为true。如果你确实是因为某些原因需要保留这个参数,则用第二种方法。

  好了,用JSLint改进后的代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
(function ($) {
    'use strict';
    $.fn.loading = function (msg, type, cssClass) {
        var prefixes = {
            warning: 'Warning: ' + msg,
            error: 'Error: ' + msg,
            info: 'Info: ' + msg,
            caution: 'Caution: ' + msg
        }, concatMsg = msg;
        if (type) {
            concatMsg = prefixes[type];
        }
        $(this).each(function () {
            var tis = $(this);
            if (msg === false) {
                tis.html('');
            } else {
                tis.html(concatMsg);
            }
        });
    };
}(jQuery));

  JSLint 指令

  你可以通过JSLint指令在你的源代码中直接定义JSLint变量。这样,你就不用在页面上来回操作。如下示例,注释中定义了jQuery全局变量,并将“unparam”设为true。

1
2
3
4
5
6
/*global jQuery*/
/*jslint unparam: true */
(function ($) {
    ‘use strict’;
}(jQuery));

  总结

  在这个简短的例子中,JSLint指出了一些明显的和一些容易忽视的错误。在实际运行代码之前,通过JSLint帮我们查找一些错误可以有效的提高我们的开发效率和代码质量。如果你真的是认真地想写出优质的代码,那么在放到服务器上运行之前先用JSLint检查一遍吧。JSLint还提供一个独立的JS文件版本,所以你也可以把它下载下来在线下运行!

  译者:

  严格模式并不是所有的浏览器都支持,这是一个浏览器支持统计表。网页前端可能暂时(甚至很长时间内)还不能遵循严格模式,但是在移动开发中显然采用严格模式更佳。不管目前是否能用上,我觉得前端工程师们都应该利用这些工具帮助自己养成良好的编码习惯,好的习惯会让你受益匪浅,在这里略矫情略夸张的引用一下电影《铁娘子》中的一句话:Watch your habits, for they become your character

  英文原文:Using JSLint to Refine Your Code,编译:伯乐在线 - 胡蓉

转载于:https://www.cnblogs.com/xuweili/articles/3385322.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/273971.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pymssql出现的错误

安装pymssql出现的错误:如下:---------------------------------------- Failed building wheel for pymssqlRunning setup.py clean for pymssql Failed to build pymssql Installing collected packages: pymssqlRunning setup.py install for pymssq…

javascript设计思维

//一.把参数当作私有变量使用 (function (a, b) {//把参数当作私有变量使用,省略了var,也节省了行数console.log(b) //undefined,所有未赋值的变量均为undefined })(window);//二.把参数作为参数使用 var obj_init function (b, d, f) {//1…

linux第一章简答

linux第一章简答题: 1、你在你的主机上面安装了一张网卡,但是开机之后,系统却无法使用,你确定网卡是好的,那么可能的问题出在哪里?该如何解决? 答:因为所有的硬件都没有问题&#xf…

(原创)一个和c#中LazyT类似的c++ LazyT类的实现

在.net 4.0中增加一个延迟加载类Lazy<T>&#xff0c;它的作用是实现按需延迟加载&#xff0c;也许很多人用过。一个典型的应用场景是这样的&#xff1a;当初始化某个对象时&#xff0c;该对象引用了一个大对象&#xff0c;需要创建&#xff0c;这个对象的创建时需要较长的…

网页选项卡的应用

&#xff08;1&#xff09;功能描述&#xff1a; 在页面中&#xff0c;设置三个不同名称的选项卡&#xff0c;当单机某个选项卡时&#xff0c;下面相对应的区域显示其内容信息&#xff0c;同时选项卡的背景色与内容信息的背景色浑然一体&#xff0c;并且字体加粗&#xff0c;表…

python 爬虫-beautifulsoup4

利用它可以不用编写正则表达式即可方便的实现网页信息的提取。 pip3 install beautifulsoup4 用法讲解&#xff1a;常用解析库&#xff1a; lxml HTML解析器 lxml XML解析器 from bs4 import BeautifulSoup soup BeautifulSoup(html,lxml) print(soup.prettify()) #格式化代…

魔兽控制命令ID

来源:http://tieba.baidu.com/p/1084211586本次技能ID大全共收录ID368条不包括重复的ID&#xff0c;物品类技能的ID使用必须将物品技能单独抽离出来并设置“物品技能false”&#xff0c;拥有命令字符串的物品请参考拥有相同字符串的4族中立技能。P.S所有ID都是按照从小到大的顺…

python爬虫框架--scrapy 基本使用

流程框架&#xff1a; 1、抓取第一页&#xff1a;请求第一页的URL并得到源代码&#xff0c;进行下一步分析。 2、获取内容和下一页链接&#xff1a;分析源代码&#xff0c;提取首页内容&#xff0c;获取下一页链接等待进一步爬取。 3、保存爬取结果&#xff1a;将爬取结果保存为…

jsp页面的使用

public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {//1.获取资源文件 InputStream isthis.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties"); Str…

python爬虫安装错误与解决方式

# 安装错误&#xff1a; error:Microsoft Visual C 14.0 is required... 下载地址&#xff1a;http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted pip install xxx.whl # 运行错误 1&#xff1a; from .. Import etree ImportError:DLL load failed pip uninstall lx…

工欲善其事必先利其器系列之:在VS里面折叠js代码

之前用vs写js的时候经常因为js代码过长而且不能像cs文件里面的方法一样进行折叠而抓狂,直到在扩展库发现了这款插件有了它就可以把代码进行折叠了 插件地址转载于:https://www.cnblogs.com/Chendaqian/p/3396702.html

python- 基础 map方法

python中map()函数 map()是 Python 内置的高阶函数&#xff0c;它接收一个函数 f 和一个 list&#xff0c;并通过把函数 f 依次作用在 list 的每个元素上&#xff0c;得到一个新的 list 并返回。 例如&#xff0c;对于list [1, 2, 3, 4, 5, 6, 7, 8, 9] 如果希望把list的每个…

C算法编程题(二)正螺旋

前言 上一篇《C算法编程题&#xff08;一&#xff09;扑克牌发牌》 写东西前总是喜欢吐槽一些东西&#xff0c;还是多啰嗦几句吧&#xff0c;早上看了一篇博文《谈谈外企涨工资那些事》&#xff0c;里面楼主讲到外企公司包含的五类人&#xff0c;其实不只是外企如此&#xff0c…

同时获取同一等级下多个class值的节点的方法

方法&#xff1a; tr_ soup.find("div", class_"mod_cont fcolor30").find_all("tr", attrs{"class":["md_tr font14 bgcolor-s","md_tr font14 bgcolor"]}) 同时获取两个不同的class.例如&#xff1a; 当Beauti…

【循序渐进学Python】6.Python中的函数

1. 创建函数 一个函数代表一个行为并且返回一个结果(包括None)&#xff0c;在Python中使用def关键字来定义一个函数&#xff0c;如下&#xff1a; def hello(name):print hello, name ! 接下来调用函数&#xff0c;并查看其返回值&#xff1a; # output: # hello,gy! # None …

求子数组的最大和

穷举法&#xff1a; int MaxSubArraySum(int a[], int n) { int i, j, MaxSum 0, tmpSum, cnt; for (i1; i<n; i) { for (j0; ji<n; j) { cnt 0; tmpSum 0; while (cnt < i) { tmpSum a[jcnt]; cnt; } if (MaxSum < tmpSum) { MaxSum tmpSum; } } } return Ma…

scrapy框架-post使用

scrapy中使用FormRequest向网页提交数据 Scrapy post使用 如何post data&#xff1a; http://httpbin.org/post FormRequest : post请求 GitHub Login 借助浏览器分析登陆行为。 分析post的内容先尝试一次错误的登陆&#xff1a;如下&#xff1a;分析&#xff1a;需要post…

duilib进阶教程 -- 改进窗口拖动 (12)

现在大家应该都知道caption"0,0,0,32"&#xff0c;是指示标题栏区了吧&#xff0c;如果想要整个窗口都能拖动呢&#xff1f; 那直接把高度改成和窗口一样不就得了~O(∩_∩)O~ 嗯&#xff0c;这样是可以&#xff0c;比如窗口高度是600&#xff0c;那么我们指定caption…

python- 基础 range方法的使用

1、第一种用法 index[1,2,0,5,9,8,10,6,4,7] for i in range(len(index)): print(index[i]) 结果&#xff1a; λ py test.py 1 2 0 5 9 8 10 6 4 7 2、第二种用法&#xff1a; index[1,2,0,5,9,8,10,6,4,7] for i in range(0,len(index),2): print(index[i]) 运…

Oracle行列转换小结

目录结构如下&#xff1a;行转列列转行[一]、行转列 1.1、初始测试数据 表结构&#xff1a;TEST_TB_GRADE Sql代码 create table TEST_TB_GRADE ( ID NUMBER(10) not null, USER_NAME VARCHAR2(20 CHAR), COURSE VARCHAR2(20 CHAR), SCORE FLOAT ) 初始…