(译)提升你的JavaScript技能


英文原文见:Leveling Up Your JavaScript

JavaScript是易上手的语言之一,却难于完全掌握。然而,很多文章常常假定你已经是个高手。

自从1995年JavaScript作为LiveScript被介绍后,我便一直使用它,内容慢慢地从客户端开发转移到服务器的安全上。在过去的五年里,我又重新聚焦在客户端。这次,我很激动地发现浏览器变得更完善、强大、并且比早期更容易调试,但JavaScript却变得更复杂和更不容易掌握。最近的一个感受是,不一定需要掌握JavaScript,但要能更好的使用它。我很高兴成为一个“好”JavaScript开发人员。

下面是我总结的一些技巧和有用的技术,它们都以实践JavaScript为依据的。分为四大部分:组织代码;linting(错误检测);测试;使用浏览器的开发工具。虽然其中一些内容对有经验的JavaScript开发人员似乎是显而易见的,但其实学习一门新语言时如果不多加注意,很容易落入坏习惯的。这些内容都帮助我升级技能、为用户带来更好的体验。这也是我们的第一目标,对吗?

这篇文章的示例代码这里下载

一、组织代码

作为一个新的JavaScript开发人员在开始学习时,他们将不可避免地在HTML页面上方写大的代码块。这个过程总是一个简单的开始。从简单的jQuery自动对焦表单字段开始,到表单验证,到一个小对话框等。经过一系列的迭代后,在一个HTML文件里有几百行JavaScript,或者可能还有几百行标签。

这种做法很容易形成一个快速脚本块在页面的顶部。但这是一个烂摊子。请停止这样做。请像躲避瘟疫一样避开这种诱惑。建议每次当你创建一个新的网站时随之创建一个空的JavaScript文件,把这个成为一个习惯。在这个脚本文件里,你也可以继续添加交互和其他客户端功能。

一旦你远离了HTML页面(不觉得更干净了么?),下一个问题你会碰到的组织代码本身。那些几百行JavaScript可能会工作的很好,但是在几个月后你第一次调试或者修改代码,你会发现自己迷失在一个特定的函数中。

所以,如果只是把代码从HTML文件中移动到另一个文件是不够的,另一种解决方案是什么?

1.1 框架

显然使用框架是解决方案。使用AngularJS或Ember或React或几百左右其他选项之一,重建整个站点为单页应用程序和MVC,然后随意玩。

或者并不是这样的。当我构建apps时我喜欢Augular,但是一个“app”和一个交互性的web页面是有区别的,就象一个ajax增强的产品目录和Gmail之间——至少几百几千行代码不同。可如果你不走框架路线,另一个选择是什么?

1.2 设计模式

设计模式是一种经过设计过的方式在表达“这有一个解决方案来处理人们在过去遇到过的一个问题”。他们肯定是有用的。Addy Osmani在这个主题写了一本优秀的书,学习JavaScript设计模式,你可以免费下载和阅读。但是我对这本书(以及类似的讨论话题)有一个疑问,就是下面这样的代码:

var c = new Car();
c.startEngine();
c.drive();
c.soNotRealistic();

抽象看,设计模式对我有意义,但实际上并没有,因为很难在web页面代码的上下文中应用它们。

1.3 模块

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

在高层面上,模块模式简单地创建一个模块来组织一块代码。你可以将相关函数集合成一个模块,然后来决定是否暴露该模块。这样就创建一个“黑盒”模块,更容易地共享给其他项目。当然你也可以把不同的模块放到单独的文件中。

让我们看看一个简单的示例模块。

var someModule = (function(){
	//stuff here
}());

一点点剥开解释。最里面function(){}是一个简单的函数开始,这是用来定义方法的。它后面的一对圆括号是用来自动调用函数的。我们返回的是一个模块,然而代码块function() { }()周围的一对圆括号才是让它成为有效的js。如果不相信,可以在控制台试试噢。最后是将结果赋给一个变量。

既然我们已经理解了这个略微奇怪的语法,那么一个实际模块模式是什么样子的?

var counterModule = (function() {
	var counter = 0;
		
	return {
		incrementCounter: function () {
			return counter++;
		},
		resetCounter: function () {
			console.log("counter value prior to reset: " + counter );
			counter = 0;
		}
	};


}());

前面的代码创建了一个模块叫counterModule,它有两个方法:incrementCounter、resetCounter。可以这样使用它们:

console.log(counterModule.getCounter()); //0
counterModule.incrementCounter(); 
console.log(counterModule.getCounter()); //1
counterModule.resetCounter();
console.log(counterModule.getCounter()); //0

所有的代码在counterModule中打包好。JavaScript的未来将提供更简单的使用方法,但是现在,模块模式处理组织代码上还是十分简单实用的。

1.4 一个模块示例

我常抱怨网上看到的一些例子是否合理(见车的例子)。这里构建一个匹配真实场景的简单例子。

你的网络游戏公司,Lyntendo(不要起诉我),有一个用户注册门户,用户必须创建自己的游戏身份。因此需要构建一个表单,用户可以选择一个名字。该名字标识符的规则会有点奇怪:

  1. 标识符必须以大写字母开始。
  2. 标识符必须是两个或两个以上的字符。
  3. 空格是允许的,但没有标点符号。
  4. 标识符可以不包括某些“淘气”字。

让我们用一个简单的表单来模拟这个场景。

<html>
	<head>
	
	</head>
	<body>
		<p>Text would be here to describe the rules...</p>
		<form>
			<input type="text" id="identifer" name="identifier" placeholder="Identifer">
			<input type="submit" id="submitButton" value="Register Identifer.">
		</form>
		<script src="app.js"></script>
	</body>
</html>

这里有上面提到的表单和一个提交按钮,还有规则描述的文字(这里我简略了)。让我们继续看看代码。

var badWords = ["kitten","puppy","beer"];
function hasBadWords(s) {
	for(var i=0;i<badWords.length; i++) {
		if(s.indexOf(badWords[i]) >= 0) return true;	
	}
	return false;
}

function validIdentifier(s) {
	//is it blank?
	if(s === "") return false;
	//must be at least 2 chars
	if(s.length === 1) return false;
	//must begin with a capital letter
	if(s.charAt(0) !== s.charAt(0).toUpperCase()) return false;
	//only letters and spaces
	if(/[^a-z ]/i.test(s)) return false;
	//no bad words!
	if(hasBadWords(s)) return false;
	return true;
}

document.getElementById("submitButton").addEventListener("click", function(e) {
		
	var identifier = document.getElementById("identifer").value;
		
	if(validIdentifier(identifier)) {
		return true;
	} else { console.log('false');
		e.preventDefault();
		return false;	
	}
});

从底部开始,有一些基本的代码是从页面上获取元素(是的,这个例子中我没有使用jQuery)然后监听按钮的点击事件。获取用户提交的标识符,然后进行验证。验证的规则就是上面所描述的。代码不算太乱,但是随着规则增加,或添加其他交互功能,将变得更加困难。让我们用模块的方式来重写。

首先,创建一个名为game.js的新文件,并在html文件中引入它。然后逻辑验证的代码放在一个模块中。

var gameModule = (function() {
	
	var badWords = ["kitten","puppy","beer"];

	function hasBadWords(s) {
		for(var i=0;i<badWords.length; i++) {
			if(s.indexOf(badWords[i]) >= 0) return true;	
		}
		return false;
	}

	function validIdentifier(s) {
		//is it blank?
		if(s === "") return false;
		//must be at least 2 chars
		if(s.length === 1) return false;
		//must begin with a capital letter
		if(s.charAt(0) !== s.charAt(0).toUpperCase()) return false;
		//only letters and spaces
		if(/[^a-z ]/i.test(s)) return false;
		//no bad words!
		if(hasBadWords(s)) return false;
		return true;
	}


	return {
		valid:validIdentifier	
	}
		
}());

现在代码看起来并没有特别大的不同,只不过被包装为一个叫gameModule的变量,且有一个API,valid。然后来看app.js

document.getElementById("submitButton").addEventListener("click", function(e) {
		
	var identifier = document.getElementById("identifer").value;
	
	if(gameModule.valid(identifier)) {
		return true;
	} else { console.log('false');
		e.preventDefault();
		return false;	
	}
});

注意到,更少的代码与DOM监听器混在一起。所有的功能验证(两个函数和一个坏词列表)现在都安全地放在模块中,使之更容易协作。

使用模块并不是火箭科学,但它清洁和简单,这是一个真正的好事!


二、Linting

如果你不知道这个词,Linting是检查您的代码的是否为最佳实践和其他问题。一个崇高的事业,对吧?我总是留下这样的印象,即Linting担心着开发人员的担心。

(关于使用的例子这边不做翻译,有需要可看英文原文)

如何使用它呢?

你可以为JavaScript找到linters(JSLintJSHint),HTML(HTMLHintW3C验证器)和CSS(CSSLint)。编辑器支持,你也可以自动化工具来安装,例如Grunt和Gulp。


三、测试

你可能听说过TDD(测试驱动开发)。这是在实际功能开发完成之前编写单元测试的概念。从本质上说,这个想法是测试帮助驱动开发。在编写代码时,测试通过后就有保证在正确的道路上前进的感觉。

我认为这是一个好想法,但它可能对每个人来说都难以实现。简单一点呢?想象一下有一组现有的代码,然后你发现一个错误。修复该错误之前,你可以创建一个测试用例来验证错误,修复它,然后使用测试,以确保它在未来保持固定的工作。就像我说的,这并不是理想的路径,但是是开发阶段加入测试的一种容易方式。

(关于使用的例子这边不做翻译,有需要可看英文原文)

对于测试框架,有JasmineQUnitMocha

测试JavaScript代码的其他选项包括QUnit和摩卡。通过一些类似Grunt的任务运行器,你可以自动运行所有测试任务,甚至使用Selenium测试浏览器本身。


四、浏览器开发者工具

最后将提到的是浏览器本身——开发工具。这个话题可以找到很多文章、演示和视频,所以我就不铺开讲。此外我相信今天所讨论的可能是web开发人员所需要的知识。写不漂亮的代码也好,不知道所有的知识点也好,但至少浏览器开发工具能帮助你找到问题所在。此时的解决方案通常是谷歌搜索。

在这里添加最后一条建议,那就是不应该只关注一个浏览器的开发工具。几年前我玩应用程序缓存,在Chrome运行时遇到问题,把开发者工具打开,但是它并没有帮助。心血来潮,我在Firefox中运行代码和使用他们的开发工具,就立即我发现了这个问题。Firefox只是纯粹地比Chrome记录请求相关的更多信息。运行一次都能纠正该问题。(好吧,这是一个谎言。Firefox显示我的问题,但经过一段时间才修复)。如果你发现自己被困,就打开另一个浏览器,查看错误报告是否提供了不同的视角。

只是碰碰运气还不够真正认识浏览器工具,以下查看主要的浏览器开发者工具的一些指导,以及最好的链接。

GOOGLE CHROME

Chrome DevTools Overview

MOZILLA FIREFOX

Firefox Developer Tools

APPLE SAFARI (AKA THE BROWSER FOR WATCHING APPLE KEYNOTES)

About Safari Web Inspector

INTERNET EXPLORER

Using the F12 developer tools”


五、更多内容

作为开发人员事情从来都没有做完的时候。写这篇文章时,你是否知道已发布的十三个JavaScript框架?这里将给出关于如何学习和如何保持——尽可能最好的一些建议。

对于学习,我会关注Mozilla开发人员网络(谷歌搜索时,尽量加上术语“mdn”),CodeSchool(商业视频培训公司的内容),和可汗学院。专门提到Mozilla开发人员网络(MDN)是因为我多年来一直觉得它不过是Netscape/Firefox网站而回避它,但后来发现这种想法很愚蠢的。

另一个建议是读代码!许多人使用jQuery,但实际上你有没有打开文件看一下它是如何建造的?阅读别人的代码是一个很好的方式去接触到其他技术和方法。另外我也强烈建议你分享自己的代码。不仅会有另一双眼睛(或成千上万的)看你的代码,你的代码也可以帮助别人。

订阅最新的新闻,我通过Cooper Press订阅的各种“每周”资讯。当我看到发布了一些新工具Foo,但可能此时我并不特别需要使用Foo,我甚至不尝试学习这个工具。但只要我记得,“嘿,有一个工具是Foo。“ 在不久的将来需要用到它时,那时再花时间去学习它即可。

crystal /
Published under (CC) BY-NC-SA in categories 前端  tagged with JavaScript