本文深入解析JavaScript可维护代码的构建方法,涵盖可理解性、直观性等五大特征。详细阐述代码约定、变量命名规范及类型标识技巧,重点讲解HTML/JS、CSS/JS及应用逻辑的解耦策略。结合尊重对象所有权、避免全局变量及使用常量等编程实践,提供提升代码质量与团队协作效率的完整指南。
可维护代码的定义
编写可维护的代码需遵循若干关键特性。
1. 可理解性:其他开发者接手后能清晰理解代码意图及实现路径。 2. 直观性:无论内部逻辑多复杂,代码表象应一目了然。 3. 可适应性:代码结构应能应对数据变化,无需完全重写。 4. 可扩展性:架构设计需预留未来核心功能的扩展空间。 5. 可调试性:出错时能提供充足信息,辅助快速定位问题。
代码约定
建立一套JavaScript书写约定是提升代码可维护性的有效手段。鉴于JavaScript的灵活性,统一的约定对其尤为重要。下文将探讨代码约定的核心概念。
1. 可读性
可维护性的基础是代码可读。可读性主要依赖于代码缩进,整齐的缩进能直观展示代码块的功能归属。常见缩进标准为4个空格,现代编辑器大多支持一键格式化。此外,注释也是提升可读性的关键,通常需在以下场景添加注释:
- 函数和方法:每个方法或函数应包含注释,说明其目的及可能使用的算法。
- 大段代码:执行单一任务的多行代码前,应添加描述该任务的注释。
- 复杂算法:对解决特定问题的独特逻辑,需注释解释实现方式。
- Hack处理:针对浏览器兼容性的特殊处理代码。
2. 变量和函数的命名
命名往往是开发中最令人头疼的环节,无论是类、变量还是函数命名,有时甚至需借助翻译工具。合理的命名对提升代码可理解性和可维护性至关重要。一般命名规则如下:
- 变量名应使用名词,如car或person。
- 函数名应以动词开头,例如getName()。
- 返回布尔类型的函数通常以is开头,如isEnable()。
- 常量应全部大写表示,如MAX_LENGTH。
3. 变量类型透明
JavaScript是松散类型语言,容易遗忘变量包含的数据类型。虽然合适的命名能缓解这一问题,但仍有三种方式可明确标识数据类型。
3.3.1、初始化
定义变量后,应赋予初始值以暗示其预期用途。
// 通过初始化指定变量类型
var found=false; //布尔型
var count=-1; //数字型
var name=""; //字符串
var person=null; //对象
3.3.2、使用匈牙利标记法指定变量类型
匈牙利标记法在变量名之前加上一个或多个字符来表示数据类型。js中最传统的匈牙利标记法是用单个字符来表示基本类型:0-对象,s-字符串,i-整数,f-浮点数,b-布尔类型。
// 用于指定数据类型的匈牙利命名法
var bFound //布尔型
var iCount; //数字型
var sName; //字符串
var oPerson; //对象
匈牙利命名法的优点是函数参数也可使用,但其缺点在于一定程度上降低了代码的可读性。
3.3.3、使用类型注释
指定变量类型的最后一种方式是使用类型注释。类型注释位于变量名右侧,但在初始化之前。
// 用于指定类型的类型注释
var found /*Boolean*/ = false;
var count /*int*/ = 10;
var name /*String*/ = "Tom";
var person /*Object*/ = null;
缺点:多行注释可能与代码块产生冲突。
上述三种指定变量数据类型的方法各有优劣,应根据项目实际情况评估选用,也可考虑学习使用TypeScript。
松散耦合
若应用的某部分过度依赖另一部分,代码即变得过紧,难以维护。Web应用中多种因素可能导致耦合过紧,因此应尽量避免这些情况,尽可能保持弱耦合代码。
1. 解耦html/JavaScript
在HTML中直接使用JavaScript,包括使用包含内联代码的<script>元素或通过HTML属性分配事件处理程序,均属于过度紧密耦合。
参考以下代码示例。
<button onclick="doSomeThing()">Click Me</button>
在此例中,可能在doSomeThing()函数可用前就已按下按钮,导致JS错误。任何对按钮行为的更改需同时修改HTML和JS,严重影响可维护性。
同理,JS中包含大量HTML字符串的情况。
// 将HTML紧密耦合到js中
function insertMessage(){
document.getElementById('container').innerHTML='<div>Hello World</div>'
}
该方法会动态生成代码块插入页面,当代码量大时,错误定位变得困难。
将HTML与JavaScript解耦可节省调试时间,更易确定错误来源,并降低维护难度:更改行为仅需修改JavaScript文件,更改标记仅需修改渲染文件。
2. 解耦css/JavaScript
Web层的另一部分是CSS,主要负责页面显示。JavaScript与CSS关系紧密,二者均位于HTML之上,常结合使用。但与HTML和JS的情况类似,CSS与JS也可能耦合过紧。最常见的紧密耦合示例是使用JavaScript直接修改样式,如下所示:
//CSS 对 JavaScript 的紧密耦合
element.style.color = "red";
element.style.backgroundColor = "blue";
遇到直接修改CSS样式的场景,建议通过修改元素标签的class类名来控制样式,这样更为便捷。
3. 解耦应用逻辑/事件处理程序
Web应用通常包含大量监听不同事件的事件处理程序,但很少能仔细将应用逻辑从事件处理程序中分离。请看以下示例:
function handleKeyPress(event) {
event = EventUtil.getEvent(event);
if (event.keyCode == 13) {
var target = EventUtil.getTarget(event);
var value = 5 * parseInt(target.value);
if (value > 10) {
document.getElementById("error-msg").style.display = "block";
}
}
}
该事件处理程序不仅包含应用逻辑,还直接处理事件。这种方式存在双重问题:首先,除事件触发外无其他执行应用逻辑的途径,导致调试困难。若未产生预期结果,难以判断是事件处理程序未被调用还是应用逻辑失败。其次,若后续事件触发相同应用逻辑,则需复制功能代码或将其抽取为独立函数。无论哪种方式,均需进行比实际更多的修改。
较好的方法是将应用逻辑与事件处理程序分离,各自处理特定职责。事件处理程序应从事件对象中提取相关信息,并传递给处理应用逻辑的方法。例如,前述代码可重写为:
function validateValue(value) {
value = 5 * parseInt(value);
if (value > 10) {
document.getElementById("error-msg").style.display = "block";
}
}
function handleKeyPress(event) {
event = EventUtil.getEvent(event);
if (event.keyCode == 13) {
var target = EventUtil.getTarget(event);
validateValue(target.value);
}
}
应用和业务逻辑之间松散耦合的几条原则:
- 勿将event对象传给其他方法;仅传递来自event对象所需的数据;
- 任何应用层面的动作均应能在不执行任何事件处理程序的情况下进行;
- 任何事件处理程序均应处理事件,然后将处理转交给应用逻辑。
牢记这几条原则可在任何代码中获得极大的可维护性改进,并为后续测试和开发创造更多可能性。
编程实践
书写可维护的JavaScript不仅关乎代码格式化,更涉及代码的功能实现。在企业环境中创建的Web应用往往由大量人员共同创作。此场景下的目标是确保所有开发者使用的浏览器环境具有一致且不变的规则。因此,建议坚持以下编程实践。
1. 尊重对象所有权
JavaScript的动态特性使得几乎任何对象在任何时间都可被修改。在企业环境中,最重要的编程实践之一是尊重对象所有权,即不得修改不属于你的对象。简言之,若你不负责创建或维护某个对象、其属性或方法,则不应对其进行修改。具体而言:
- 不要为实例或原型添加属性;
- 不要为实例或原型添加方法;
- 不要重定义已存在的方法。
2. 避免全局变量
与尊重对象所有权密切相关的是尽可能避免全局变量和函数。这有助于创建一致且可维护的脚本执行环境。最多创建一个全局变量,让其他对象和函数依附其中。参考以下示例:
// 两个全局量——避免!!
var name = "Nicholas";
function sayName(){
alert(name);
}
该代码包含两个全局量:变量name和函数sayName()。实际上,可创建一个包含两者的对象,如下例所示:
// 一个全局量——推荐
var MyApplication = {
name: "Nicholas",
sayName: function(){
alert(this.name);
}
};
重写后的代码引入了单一全局对象MyApplication,name和sayName()均附加其上。此举消除了前段代码中的一些问题:首先,变量name覆盖了window.name属性,可能与其他功能冲突;其次,它有助于消除功能作用域之间的混淆。调用MyApplication.sayName()在逻辑上暗示,任何代码问题均可通过检查定义MyApplication的代码来确定。
3. 使用常量
以下类型的值适合使用常量定义:
- 重复值:任何在多处用到的值均应抽取为常量。这限制了因一个值变更而另一个未变更导致的错误。这也包含CSS类名。
- 用户界面字符串:任何用于显示给用户的字符串,均应抽取出来以方便国际化。
- URLs:在Web应用中,资源位置易变更,故推荐用一个公共地方存放所有URL。
- 任意可能会更改的值:每当使用字面量值时,都应自问该值未来是否变化。若答案为“是”,则该值应被提取为常量。
以上就是教你如何写出可维护的JS代码的详细内容,更多关于写出可维护的JS代码的资料请关注本站其它相关文章!