提高你的Javascript水平

举报
竹叶青 发表于 2020/02/17 18:09:46 2020/02/17
【摘要】 前言今天分享的这篇文章比较适合js初学者,是由坚持阅读分享第一期的两位童鞋翻译与校对,他们分别是@安生与@墨白。整篇内容从模块、代码审查以及最后的测试上都做了介绍。正文从这开始~JavaScripts是一种易学难精的编程语言。然而很多文章的内容都是假设你已经熟练掌握了js编程技巧。在1995年JavaScript作为LiveScript面世时,我就开始使用它了,但后来我逐渐从客户端开发人员,...

前言

今天分享的这篇文章比较适合js初学者,是由坚持阅读分享第一期的两位童鞋翻译与校对,他们分别是@安生与@墨白。整篇内容从模块、代码审查以及最后的测试上都做了介绍。

正文从这开始~

JavaScripts是一种易学难精的编程语言。然而很多文章的内容都是假设你已经熟练掌握了js编程技巧。

在1995年JavaScript作为LiveScript面世时,我就开始使用它了,但后来我逐渐从客户端开发人员,转到服务端安全的领域。。在过去的五年里,我重新关注客户端开发。我惊喜地发现浏览器功能更加强大,也更容易调试。但JavaScript开始变得复杂且不易掌握。最近我转变了自己的心态,没必要去精通JavaScript,但我可以选择让自己js编写水平更好。我很乐于成为一个“好”的JavaScript开发人员。

下面是一些我认为在编写JS代码方面很实用的技巧和技术,比如‘代码组织’、‘代码检查’、‘测试’以及‘使用浏览器开发者工具’。其中一些对于有经验的JS开发者来说是很简单的事,但却是新手非常容易养成的坏习惯。这些规范已经帮助我提高了我的技能,也给我的用户带来更好的体验。这不正是我们的首要目标吗?

组织

作为一个JS开发新人,不可避免地会在HTML页面顶部放上一堆代码。开始总是很简单,一段简单自动对焦到表单字段的jQuery,接着可能就是表单验证,然后是网页中常见的弹出框——就是那种会中断人们阅读内容,以便分享到FaceBook表示他们喜欢这个网站。经过一些迭代后就会变成几百行的JS代码,淹没在有几百行标记的HTML文档里面。

这简直一团糟,所以不要这样做。这个听起来很简单,以至于我都认为不需要把它写下来。但是,当你匆匆忙忙在赶一个快速脚本时,会非常容易在页面的顶部形成堆积。为了避免这种情况,当你在制作一个新的网站时养成新建一个JS文档的习惯。同时引用script脚本标签,之后你就可以方便地添加交互或其他客户端的特性了。

一旦你离开HTML页面(有没有感觉变得更加简洁?),下一步就要组织代码了。那些几百行的JS代码可能能够运作,但你在几个月后再次调试或修改时,你会发现你只是想单纯找到一段函数而已。

所以如果简单地从HTML中移动一些js代码到其他文档还不够,下一步该做什么呢?

框架

很明显框架是解决之道。把所有东西搬到AngularJS、Ember、React或者其他。重建整个网站成单页面应用或者MVC会令人抓狂的。

或者并不需要?不要误解,当我做App时我喜欢用Angular,但app和网页之间有互动性方面的区别。Ajax-enhancedproduct catalog和Gmail也有区别——至少几百行的代码不同。但如果你不打算使用框架,会有什么其他的选择呢?

设计模式

关于设计模式有一个说法就是“这是可以人们处理过去遇到的问题的经验总结。”它们肯定是有用的。Addy Osmani写了一本关于这个主题的好书——《学习JS设计模式》,你可以免费下载和阅读我推荐的这本书。但关于这本书我有一个问题(以及对于这话题类似的讨论),你可以看到像这样的代码:



理论上,设计模式对我来说是有意义的,但实际上并不。很难把它应用在一个实际的网页上下文环境中。

模块

在所有我阅读过的模式中,我觉得模块模式是最简单以及最易适用于在现有代码中的。

高层次的模块模式会用一组代码简单地创造一个闭包。你可以用一个相关的集合函数,把它们放进一个模块,然后选择你想要公开的接口。这将创建更容易在其他项目的应用的“黑盒子”代码。你也可以在模块中将代码移到不同的文档。

来看一个关于模块模式的简单例子。我知道刚开头会有个语法看起来很奇怪,不用着急,让我们先来看下这个“容器”,我会解释不同的点的:



会对这些圆括号感到疑惑吗?老实说,尽管我了解JavaScript,我仍不是容易转过圈来想明白它们在做些什么,于是,我换了一种思考方式,从代码块里面开始阅读代码。



从一个简单的函数开始,在这里面定义的方法可以在模块中调用.



最后一对括号会自动运行函数。我们会返回函数中定义的东西,当然现在它还是空的。但是高亮显示的JavaScript代码现在是无效的。那么如何让它有效?



function(){}()里面的圆括号使得JS语句变得有效。不信可以打开你的开发者工具控制台然后尝试自己输入。

回到一开始……



最后一件要做的事是把函数自动运行的结果赋给一个变量。尽管我个人完全明白这段代码的含义,但每次我看到这段代码我都会停下来,稍微提醒自己这段代码的含义。不好意思提起,我在编辑器中保持着这段代码,这样我就可以复制和粘贴这段“空”模块来进行快速复用。

既然我们已经明白了这种有点奇怪的语法,那么真正的模块模式是什么样子的呢?




前边的代码创建了一个叫做counterModule的模块。它包括两个函数:incrementCounter和resetCounter。运行可以看到:



想法就是打包好在counterModule里面的所有这些代码。打包是入门级的东西,未来的JS会提供更加简单的方法来做这些事情,但现在而言我发现模块模式非常简单,它是一种处理组织问题的简单实用的方法。

一个实用的模块例子

我们来构建一个可以匹配真实情境的简单例子。我尽可能简单地讲,同时会有一些你可能会在实际的web应用中遇到的场景。

假设你的网络游戏公司Lyntendo,有一个用户注册入口让用户创建游戏身份。你需要构建一个可供用户选择名字的表格。对于身份规则有些要求:

  • 用户名必须用大写字母开头。

  • 用户名必须要两个字母及以上的长度。

  • 允许空格,但不能有标点符号。

  • 用户名不能包括非主流词汇。

首先,我们来写一个非常简单的表格。



以上提供了表格以及提交按钮,同时也引进了描述规则的js文件,现在让我们来看一下代码。



从底部开始,我用一些基本代码来获取页面中的元素(在这我没有用jQuery),然后监听按钮的click事件。获取用户输入的值然后把它传到我写的验证方法中去。验证输入的值是否符合上面我描述的规则。代码不太复杂,但当我的验证规则增加并且我想在页面中加入其它交互的点时,代码就会变得复杂了。让我们来重写下这个模块。

首先,创建一个新的js文件叫game.js,接着通过script标签引用在我的index.html。然后我把描述验证逻辑的内容放到一个模块中。



这和之前并没有太大区别,但现在它已打包好了放在gameMoudule的变量中,并且它有一个有效的API。现在看下app.js。



相比于之前的代码,可以看到少混合了很多关于DOM监听的代码。所有验证的功能(两个函数和一个不符合验证规则的坏词列表)现在安全地放在模块中,让代码更容易工作。在你的编辑器,你也可以完成代码的模块方法。

代码模块化不是必要和复杂的事,但它更简洁和简单,是非常好的东西!

代码检查

代码检查适用于在练习或其他问题中来检查你的代码。

你记得那些你重命名的函数然后提醒自己你会待会修补它的时候吗?

你记得当你定义一个函数去接收两个参数但最后却从头到尾只使用了一个的时候吗?

你记得有时写过一些非常愚蠢的代码吗?那些不能运行的,比如fuction和functon。

代码检查可以帮上忙。对于所有人来说,代码检查不只是好的练习,也可以是语法和基本的逻辑检查。而且,利用代码检查工具帮助我们改正“我知道怎么修改代码,等我有时间的时候再去修改代码”这样的坏习惯。所以,很多现代编辑器都有代码检查插件。我现在的编辑器(Sublime,Brackets,Visual Studio Code),所有都支持提供代码检测实时反馈。

举个例子,这是一份VisualStudio Code的报告。我故意把一些代码写得很烂。



上图Visual Studio Code报了我代码中的一些错误。VSC的linter,和大多数的linters一样,会提供关于你关心什么和你会认为什么是错误(“必须修复”)与警告(“别懒惰了,赶紧修复吧”)之间的选项。

如果你不想要安装任何东西或配置你的编辑器,可以在JSHint.com进行在线代码检查。JSHint可能是最受欢迎的linter,它基于另一个linter:JSLint(两者是不同的)。JSHint比JSLint严格的多。你可以直接在编辑器或通过命令行使用JSHint,当然,最简单的使用方法就是在网页上尝试一下。



左边的代码是实时的编辑,右边是关于左边代码的实时报告。简单在代码中引入一个低级错误就能大概清楚流程了。我把main函数改成main2:



站点立刻就报了两个错误。但这些并不是语法错误。似乎上面的代码看起来没有问题,但JSHint注意到了你可能没意识到的问题(这只是一个5行的代码块,但想象一下在一个偌大的文档中到处都是函数而且被调用的函数分散在许多行中,人工检查代码会疯的)。




那么实际的例子如何,下面的代码中(现在使用jQuery了),是一些简单的JS处理表单验证。这种琐碎的事,可能现在一半的JS代码都在做(还有突然出现要求你点击“喜欢”这个网站的模态框)。



这段代码开头写了两个函数来帮助验证年龄和邮箱。然后我们有一个document.ready代码块来监听表格提交。获取来自三个区域的值,检查是否空白(或无效),然后警告表格无效或者继续执行(或者在我们的例子中,表格就这样了)。

我们把这些放进JSHint然后看看可以获得什么:



天呐,有好多问题,但是相似的问题发生了很多次,刚开始使用linters时是这样。我并没有特意制造许多独特的错误,只是重复了许多相同的错误。第一个非常简单——使用严格相等“===”来取代“==”。这里严格测试值是否是空字符串。好吧,我们先来修复它。



下面是JSHint里面更新的报告:



现在清楚了。下一个块是关于“未定义的变量”。这看起来很奇怪,如果你使用过jQuery的话,你就会知道'$'。badForm存在的问题很简单——我忘记用var给他设定范围。但我们如何修复$呢?JSHint提供一个方法去配置代码怎样去检查出问题。通过添加内容(类似注释)到我们的代码,我们可以让JSHint知道$变量是作为全局存在的而且可以放心使用的。



然后是JSHint的更新报告:



啊,终于快完了。最后问题是一个很好的例子,这个例子说明了JSHint可以提供除了代码错误之外的信息。在这个例子中,我忘写了一个处理年龄核实的函数。我已经创建了validAge,但在表格检查区域,并没有调用它。函数虽然只有一行,但可以以防后面验证更繁杂,所以我决定保留它。这是最终的代码版本(demo_jshint/app.js)



这个版本最终“通过了”JSHint的测试。这个代码还不是完美的。现在有validAge和invalidEmial这两个验证函数。如果通过验证的话,两个验证函数的返回值不同,一个是true,一个会是false。如果返回值是一致的会更好。同样认识到每次验证运行,jQuery都会被获取来自DOM的三个节点。

它们只需要加载一次。我应该创建一些变量在提交块之外,然后每次都来复用它们。就像前边说的,JSHint不是完美的,但经过JSHint检测的最终版本肯定会比最开始的更好,而且也没有花费很多时间来修改代码。

关于代码检测工具,有JS的linters(JSLint和JSHint),HTML的linter(HTMLHint和W3C Validator),CSS的linters(CSSLint)。伴随着编辑器的支持,如果你喜欢的话也可以使用自动化工具,比如Grunt和Gulp.

测试

首先,许多编辑器会自动测试你的代码。比如说,在Brackets,你可以使用xunit扩展,右键单击JS文档然后生成一个测试



这个扩展会尝试根据代码写一个测试。这个测试会一直存在着而你需要更新一些实际的数据,但最重要的是它会帮助你减少繁重的测试工作。



一旦你开始更新细节,扩展会自动运行你的测试。现在知道写测试很重要了吧?



你可能听过TDD(Test DrivenDevelopment)。这是一个概念,描述的是在开发实际功能之前编写单元测试。从本质上说,就是测试驱动开发。当你写完代码并且代码通过测试时,你可以确保你的方向是对的。

想象你有一组还可以运行的现有代码,然后你发现了一个bug。在你修复bug之前,你可以写一个测试去验证这个漏洞,然后修复它。之后确保在你未来工作中也能通过这个测试将它修复。这不是一个理想的路径,但可以是一种渐进增加到包括测试的所有开发阶段的方法。

在这个示例中有一个简化数字的小函数。在这个样例里109203可以被简化为109K。而210290可以转化为2M。看下这段代码,我们一起来找一找有没有bug:



当输入9999,它会返回1万。现在看起来简化是有效的,但这段代码把所有小于1万的数字都返回它们的自身的值。这很容易修正,不过,我想为它尝试写一个测试来作为示范。测试框架使用Jasmine。Jasmine可以用通俗易懂的语言去写测试,并且很容易进行执行操作。最快的方法就是下载一个库。一旦完成并提取,会发现有一个SpecRunner.html的文档。这个文档处理加载你的代码,加载你的测试,然后执行测试并创建报告。它需要压缩包里面的lib文件夹,但你可以复制SpecRunner和lib到你的web服务端。

打开SpecRunner.html然后你可以看见最上面写着:


在第一行内容下面你会想要删除现有行然后简单加上一个scipt的标签指向你的代码。如果你得到这篇文章的压缩包你可以看见我的代码在demo4的文档中有一个formatter.js。接下来你会想要添加一个script标签去指向spec或者测试。可能你还没见过Jasmine,但看下spec。它非常易读。



基本上我的测试是在说当9999传送到库时,它应该输出9999才对。如果你在浏览器打开SpecRunner.html你可以看见它报错了。



这个修复简单点。改变9999为10000条件。



现在你运行下就会有比较好的结果的了:


查看模块,你可以尝试把一些相关的测试写成组件。在实际项目中,尽量认真测试和尽可能的覆盖到每一种可能。尝试下一个很棒的日期/时间库馆Moment.js,有超过五万七千的测试。

其他关于测试的JS代码的选择包括Qunit和Mocha。在代码检查你可以对任务的执行自动测试,像Grunt,你甚至可以在完整的前后端环境下通过用Selenium测试浏览器来测试你的项目。

浏览器开发者工具

最后一个我会提到的工具就是在浏览器里边的——开发者工具。你可以找到许多关于这个话题的文章、介绍和视频,所以我不会讲太多,除此之外我相信,这或者是一件我认为对web开发者来说的“必备知识”。你不知道的话也无所谓。但浏览器开发者工具至少可以帮助你找到关于错误的信息,此时的解决方案通常是谷歌一下。

最后一点的小建议,那就是不应该只关注到一个浏览器开发者工具。我在几年前就尝试了应用程序缓存,然后把我的代码放到Chrome中来查看问题。我也有打开我自己的开发者工具,但它不起作用。心血来潮我就打开代码到FireFox并使用它们的开发者工具,很快就找到了问题所在。相比于Chorme,Firefox报告更多的信息。运行一次就足以让我修正问题了(好吧,我骗你的,Firefox告诉我问题所在但修复的时间会有点长。)如果你被困住了,只需打开另一个浏览器然后看看它所提供的不同角度的错误报告。

如果没使用过你的浏览器工具,这里是一些关于如何在主流浏览器查看它们的操作指南。

Google Chrome

打开开发者工具,点击浏览器右上方的汉堡菜单图标,选择“更多工具”,然后“开发者工具”。也可以用键盘打开,比如在OSX中组合键是CMD+SHIFT+C。你可以在“Chrome DevTools Overview”找到Chrome开发者工具的文档。

Mozilia Firefox

打开开发者工具,在主菜单找到“工具”,然后点击“网站开发者”和“切换工具”。注意Firefox有一个很酷的工具栏可以用来发出命令以及打开开发者工具。这个同样可以从相同的菜单中启用。你可以在Firefox Developer Tools学到更多。

Apple Safari

在你能使用开发者工具工作之前,你必须启用“开发”菜单。到Safari的偏好设置,然后选择“优先”,单击“在主栏显示开发菜单”。接着你可以选择“开发”菜单,然后使用“显示Web检测”(或者下面的三个条目)来打开开发者工具。你可以在“About Safari Web Inspector”阅读更多。

IE

点击右上角的齿轮图标(或按下F12)打开IE的开发者工具,你可以在“Using the F12 developer tools”阅读更多。

学习吧

作为开发者,有时似乎我们的工作从来没有完成的那一刻。当写这篇文章时,已经有超过13个的JS框架被制造出来了。所以最后有一些关于如何尽可能学习的建议。

关于学习,我主要在MozilaDeveloper Network(当你谷歌时,前面要加上一个“mdn”),CodeSchool(一个培训公司很好的商业视频),和Khan Academy。我想要专门拿MozillaDeveloperNetwork(MDN)出来讲,之前我愚蠢的以为它只是一个Netscapr/Firefox的站点而一直没使用它。

另一个建议是阅读代码。我们中的大部分人用过jQuery,但你们有没真真切切打开文档看下它是怎么写的?阅读其他人的代码是发现其他技术和理论的很好途径。强烈鼓励你分享你的代码。不只因为你会有别人帮你review代码,你可能也会帮助到别人。几年前我看过一个初级程序员分享了一些代码,他出现了一些典型的新手错误,但他也用了一些很棒的技术呀。

为了跟紧当下的新闻,我通过CooperPress订阅了各种每周通讯。他们有HTML周报,JS周报,Node周报,Mobile周报等等。这样的资源很多,但要量力而行。当看见一些新的工具发布后,可能那时候我不需要它,我就不会去试着使用,但会记在脑海里说“有一个工具叫做……”,这样我将来需要用到的时候就能用上了。

关于本文

译者:@安生

校对:@墨白

原文链接:http://developer.telerik.com/featured/leveling-up-your-javascript/

本文转载自异步社区

原文链接:

https://www.epubit.com/articleDetails?id=NC7E3EF907B800001C0AF1C503C5514C3


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。