JavaScript之最佳实践(可维护性、性能优化)

可维护性

编写可维护性代码很重要,因为开发人员的大部分时间都耗在别人编写的代码上,很少有时间去编写新的代码,开发工作是别人的成果上开展的。那么可维护性代码在这个时候就很重要了,能节约开发人员的大量时间。

什么是可维护性代码

可维护性代码需要遵循以下特点:
  • 可理解性,其它开发人员能接手代码,并能理解其意图和途径
  • 直观性,代码中的内容一看就能明白,不管多么复杂的操作。
  • 可适应性,代码以一种数据上的变化而不要求完全重写的方式编写。
  • 可扩展性,考虑到未来,可允许对主要功能进行扩展
  • 可调试性,出现问题,代码能够给出确定信息让开发人员尽快找出问题所在


代码约定

让代码变得可维护的最简单的方法就是形成一套JavaScript中书写约定。


可读性

可维护性,首先它必须可读。可读性的大部分内容跟缩进有关,缩进用空格缩进而不用制表符,因为制表符在不同的编辑器中有不同的效果, 一般缩进采用4个空格为一缩进

提高可读性的另一个方法就是 代码注释。它能告知开发人员此处代码是做什么的,有什么意义,方便开发人员进行维护,一般在下列情况下需要代码注释:

  • 函数和方法,当定义一个函数或者方法,使用代码注释,用于描述目的和完成任务所需的算法。
  • 大段代码,完成某单个任务的多行代码,给一个完成任务的描述。
  • 复杂的算法,使用某独到的算法完成任务,使用注释可以说明此算法的目的,含意。
  • Hack,当需要解决浏览器兼容问题时,使用一些Hack技术,书写注释,能更好的解释解决方法的作用。

函数和变量命名

适当地给函数和变量命名是让代码可理解性和可维护性的一个有效方法,规则如下:
  • 变量名应为名词
  • 函数名以动词开头,如:getName()。返回布尔值的函数以is-开头。
  • 变量和函数必须使用符合逻辑的名字,无需担心长度问题,后期可以通过压缩来解决名字长度问题。避免使用无用变量名。


变量类型透明

由于JavaScript变量松散性的,所以很容易让人忘记该变量保存的是什么类型的数据。所以有三种方法表示变量数据类型的方式。

第一种就是初始化变量,初始化变量后,将来该变量保存的应该就是初始化值的类型。
var a = 1,
b = "hi";

a将来保存的是数字类型值,b将来保存的是字符串类型值。

第二种方法就是在变量的前面加上一个字符来提示该变量保存着什么类型的值。该字符可以是:n、o、s、b分别表示数字类型、对象类型、字符串类型和布尔类型。
var na = 2,
sw = "hi";

这样a就表示保存数字类型,w保存着字符类型。

第二种方法就是添加注释,在变量与赋值符号之间添加注释,注释该变量保存着什么类型的值。
var a /* number */ = 1,
w /* string */ = "hi";


松散耦合

所谓的松散耦合,就是将HTML和CSS分离,即将内容与样式分离,将HTML和JavaScript分离,将内容与行为分离,将CSS和JavaScript尽量分离,将样式与行为分离。将CSS文件通过外部引入到页面中,将JavaScript通过外部引入到页面中。有时我们需要通过JavaScript动态地为页面添加样式,这时,我们只需用JavaScript更 改样式类即可。
显示问题唯一来源是CSS,行为问题唯一来源是JavaScript,在这些层次之间保持松散耦合可以让代码更容易维护。



编程实践


尊重对象所有权
不要为实例或原型添加属性
不要为实例或原型添加方法
不要重定义已存在的方法


避免全局量
不要过渡使用全局变量或全局函数。


避免与null进行比较
如果值是一个引用类型,用instanceof检查其构造函数。
如果值是一个基本数据类型,用typeof检测属于哪个类型



性能

随着JavaScript的诞生,使用这门语言来编辑网页的开发人员越来越多,相对的,效率低的代码也越来越多,这有一些方法来改变运行性能。

注意作用域

随着作用域链上作用域的数量的增加,访问当前作用域外的变量所有时间也在增加,访问全局作用域总比访问局部作用域所有的时间多、速度慢,因为还要遍历作用域链。那么只有减少在作用域链上的时间来提升整体的运行性能。

避免全局查找
优化脚本性能最重要的方法之一就是注意全局查找。使用全局变量和函数比局部变量和函数耗时、开销大,因为涉及作用域链的查找。

function upDateUI() {
    var imgs = document.getElementsByTagName("img");
    for (var i = 0, len = imgs.length; i < len; i++) {
        imgs[i].title = document.title + "image" + i;
    }

    var msg = document.getElementById("msg");
    msg.innerHTML = "update complete";
}

upDateUI()函数包括了三个对全局document对象的引用,如果页面中有十张甚至上百张图片,那么在for循环中对document对象的引用要执行十次甚至上百次,也就是说要在作用域链上查找相同对象上百次,这是一件损耗性能的工作。 我们可以创建一个局部变量,使其指向document对象,这样就可以限制为一次访问全局对象document(只执行一次全局查找),也只需在作用域链上执行一次全局查找足以。虽然只访问一次,但这个局部变量是一个指针,指向document对象的,访问一次就已经查找到document对象了,所以尽管多次调用这个局部变量,document对象却早已查找到,但此时无需在作用域链上查找了,因为局部变量已经指向这个对象了。

function upDateUI() {
    //局部变量指向document对象,访问一次就已经查找到document对象了。
    var obj = document;
    var imgs = document.getElementsByTagName("img");
    for (var i = 0, len = imgs.length; i < len; i++) {
        imgs[i].title = obj.title + "image" + i;
    }

    var msg = document.getElementById("msg");
    msg.innerHTML = "update complete";
}

现在函数只有一次全局查找。

机巧:将 在一个函数中会 用到多次的全局变量存储在 一个局部变量中是一个减少损耗的好办法。


避免with语句
我们知道,with语句有自己的作用域,它会扩充执行环境,所以with语句会增长作用域链长度,因此要避免使用with语句。



选择正确的方法

性能问题的一部分原因来自于算法的复杂程度和方法的复杂程度。

避免复杂的算法
算法的复杂性也会影响到性能,算法越是复杂,那么损耗就越大,执行代码所需要的时间就越长。因此,避免太复杂的算法也是降低损耗的一个办法。

优化循环
  • 减值迭代:一般循环是从0开始,增加到某个终止值为止的迭代器。大多数情况下,从最大值开始,在循环中不断减值的迭代器更高效。
  • 简化终止条件:也就是终止条件的算法复杂程度要减小。
  • 简化循环体:最大限度地简化循环体语句。
  • 使用后测循环:也就是多用do-while循环语句(避免最初终止条件的计算,也就是第一次循环时,不会计算终止条件)。



展开循环
也就是知道循环次数且循环次数少的情况下,就不用循环,展开来。

例如,我们知道某循环会执行3次即循环次数为3,传统书写为:
var arr = ["red", "blue", "yellow"];
//减值迭代器
for (var i = arr.length - 1; i >= 0; i--) {
    console.log(arr[2 - i]);
}

当我们展开循环为:
var arr = ["red", "blue", "yellow"];

console.log(arr[0]);
console.log(arr[1]);
console.log(arr[2]);

这样展开循环可以消除建立循环和处理终止条件的额外开销。


避免双重解释
例如:
eval("alert('hello')");

这个例子会实例化一个新的解析器,这样就会有开销,不如直接将代码提取白出来:
alert("hello");

提升性能的其它方法
这些方法都次要的,不过处理好的话,对提升性能也有所帮助。

  • 原生方法快,JavaScript中的原生方法比自已定义方法快,比如常用的Math函数中的属性,比起自己定义的方法快。
  • switch语句快,如果有复杂的if-else语句,可以转换成单个的switch语句。
  • 位运算符比较快。



最小化语句数

减少多个变量声明
当我们声明多个变量时,往往用多个var来声明,

var a = 21;
var b = "hello";
var c = true;

我们可以只用一个var来声明这些变量:

var a = 21,
b = "hello",
c = true;

使用数组和对象字面量
当我们创建一个数组并初始化时,
var arr = new Array();

arr[0] = 1;
arr[1] = "hello";
arr[2] = true;

可以用数组直接将元素值插入:
var arr = [1, "hello", true];


在创建一个对象并初始化时,
var obj = new Object();

obj.name = "tom";
obj.age = "21";
obj.sayName = function () {
    alert(this.name);
};

我们可以用对象字面量法创建一个对象:

var obj = {
    name : "tom",
    age : 21,
    sayName : function () {
        alert(this.name);
    }
};



优化DOM交互

使用innerHTML
对于小的DOM的更改,createElment()、appendChild()以及innerHTML这三种方法的效率差不多,而对于大的DOM的更改,建议使用innerHTML更好。

DOM交互开销很大,所以要限制DOM的交互次数。


部署

压缩文件
压缩涉及两个属性:代码长度和配重。代码长度指:浏览器所要解析的字节数。配重指:服务器实际传到浏览器的字节数。

压缩一般有如下操作:

删除额外的空格(包括换行符)
删除所有注释信息
缩短变量名


压缩HTTP

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值