一:可维护性
(1)什么是可维护的代码:
1.可理解性
2.直观性
3.可适应性--代码以一种数据上的变化不要求完全重写的方法撰写
4.可扩展性--在代码架构上已考虑到在未来允许对核心功能进行扩展
5.可调实性
(2) 代码约定
1.可读性--在代码中加入必要的注释进行描述
2.变量和函数命名
3.变量类型透明: 例: var found /* :Boolean */ ---加入注释确保变量类型确定并可见
(3)松散耦合:只要应用的某个部分过分依赖于另一个部分,代码就会耦合过紧,难以维护。
1.解耦HTML/JavaScript
2.解耦css/javascript
3.解耦应用逻辑/事件处理程序:较好的方法是将应用逻辑和事件处理程序相分离,
这样两者分别处理各自的东西。一个事件处理程序应该从事件处理对象中提取相关信息,并将这些信息传送到处理应用逻辑的某个方法中。
(4)编程实践
1.尊重对象所有权
(1)不要为实例或原型添加属性
(2)不要为实例或原型添加方法
(3)不要重定义已存在的方法
2.避免全局变量
可以使用功能性全局命名空间
var wrox = {};
有关name的: wrox.aboutName = {}
有关age的: wrox.aboutAge = {}
虽然命名空间会需要多写一些代码,但是对于可维护的目的而言,是非常值得的。命名空间有助于确保代码可以在同一个页面上与其他代码以无害的方式一起工作。
3.避免与null进行比较
代码中null越少,就越容易确定代码的目的,消除不必要的错误。
4.使用常量
比如:
function validate(value){
if( !value ){
alert("Invalid value!");
location.href = "/error/invalid.php";
}
}
可以通过将数据抽取出来变成单独定义的常量的方式,将应用逻辑与数据修改隔离开来
var Constants = {
INVALID_VALUE_MSG: 'Invalid value!',
INVALID_VALUE_URL: '/error/invalid.php'
}
function validate(value){
if( !value ){
alert(Constants['INVALID_VALUE_MSG'] );
location.href =Constants['INVALID_VALUE_URL']
}
}
这些变化可以允许数据在无需接触使用它的函数的情况下进行变更;
在将数据和他的使用逻辑进行分离时,要注意的值的类型如下所示
1.重复值:任何在多处重复使用的值都应该抽取成一个常量
2.用户界面字符串:任何用于显示给用户的字符串,都应该被抽取出来以方便国际化
3.urls:推荐一个公共地方存放所有url
4:任意可能被更改的值:如果这个值以后会被更改,那么就应该提取出来作为一个常量;
二:性能
(1)注意作用域:只要能减少花费在做用域上时间,就能增加脚本的整体性能。
1.避免全局查找
funtion updateUI(){
var images = document.getElementsByTagName('img');
for( var i = 0,len = images.length; i < len; i++){
imgs[i].title = document.title + 'images' + i;
}
var msg = document.getElementsById('msg');
msg.innerHtml = "update complete.";
}
变化为:
funtion updateUI(){
var doc = document;
var images = doc.getElementsByTagName('img');
for( var i = 0,len = images.length; i < len; i++){
imgs[i].title = doc.title + 'images' + i;
}
var msg = doc.getElementsById('msg');
msg.innerHtml = "update complete.";
}
通过将document对象存放在本地的doc变量中,函数中只有一次的全局查找,速度更快。
将一个函数中会用到多次的全局对象存储为局部变量总是没错的
2.避免with语句
with语句会创建自己的作用域,因此会增加其中执行的代码的作用域链的长度。
由于额外的作用域链查找,在with语句中执行的代码肯定会比外面执行的代码慢
(2)选择正确的方法
1.避免不必要的属性查找
var value = 5;
var sum = 10 + value;
alert(sum)
以上代码的整体复杂度为O(1),O(1)表示,不管有多少值,需要获取常量值的时间都是一样的,获取常量值是非常高效的过程;
在javascript中,访问数组元素也是一个O(1)操作
换言之,在js中,常量操作和数组操作都是O(1)的算法复杂度;
使用变量和数组要比访问对象上的属性更有效率;后者是一个O(n)操作
对象上任何属性查找都要比访问变量或者数组花费更长时间;
2.优化循环:
3.展开循环
4。避免双重解释
5.性能的其他注意事项
(1)只要有可能,使用原生方法而不是自己用js重新写一个。原生方法都是用诸如C/C++之类的编译型语言写出来的,所以要比js的快很多很多。
(2)switch语句较快:将复杂的if-else转换为switch语句
(3)位运算符较快
(3)最小化语句数:完成多个操作的单个语句要比完成单个操作的多个语句快;
1.多个变量声明:
//4个语句---很浪费
var count = 5;
var color = 'blur';
var values = [1,2,3,4];
var now = new Date();
转换为:
//一个语句
var count = 5,
color = 'blur',
values = [1,2,3],
now = new Date();
2.插入迭代值:
var name = values[i];
i++;
转换为:var name = values[i++];
3.使用数组和对象字面量来创造函数和变量;
(4)优化DOM交互:在js中,dom毫无疑问是最慢的一部分。理解如何优化与dom的交互,可以极大提高脚本完成的速度;
1.最小化现场更新
一旦你需要访问的dom部分是已经显示在页面的一部分,那么你就是在进行一个现场更新;
var list = document.getElementById('myList'),
item,
i;
for(var i = 0; i < 10; i++ ){
item = document.createElement('li');
list.appendChild(item);
item.appendChild(document.createTextNode("item" + i)));
}
转换为:
var list = document.getElementById('myList'),
fragment = document.createDocumentFragment(),
item,
i;
for( var i = 0; i < 10; i++ ){
item = document.createElement('li');
fragment.appendChild(item);
item.appendChild(document.createTextNode("item" + i)));
}
避免频繁的dom操作,最好先将所有dom操作存储起来,然后一次性插入到文档结构中;
2.使用innerHTML
推荐大小都使用使用innerHTML来创建dom方法。
var list = document.getElementById('myList'),
html = '',
i;
for( var i = 0; i < 10; i++ ){
html += "<li> item " + i + "</li>";
}
list.innerHTML = html;
3.使用事件代理
页面上的事件处理程序的数量和页面响应用户交互的速度之间有个负相关;为了减轻这种惩罚,最好使用事件代理;
三:部署
1.构建过程:
你的代码应该在编译压缩之后放入浏览器中,理由如下:
(1)知识产权问题:避免别人从有完整注释代码中找到漏洞;
(2)文件大小:
(3)代码组织:组织代码要考虑到可维护性并不一定是传送给浏览器的最好方式;
2.验证
使用自动构建工具来完成代码验证,如webpack;
3.压缩
当谈及js文件压缩,其实是在讨论两个东西,代码长度和配重;
代码长度:浏览器所需解析的字节数
配重:实际从服务器传送到浏览器的字节数
(1)文件压缩
压缩器一般进行如下一些步骤
1.删除额外的空白(包括换行)
2.删除所有注释
3.缩短变量名
(2)HTTP压缩