编写可维护性的代码:
- 可理解性:其他人可以接手代码,而无需解释
- 直观性:代码一看就明白,无论操作过程多么复杂
- 可适应性:代码以一种数据上变化不要求完全重写的方法撰写
- 可扩展性:在未来可对核心功能进行扩展
可读性:
- 每个函数和方法都应该包含一个注释,描述其目的和用于完成任务所使用的算法
- 大段代码需要在前面放置一个描述任务的注释
- 复杂的算法,需要在注释中说明思路
- Hack,需要注释说明
变量名应为名词,如car
。函数名应该以动词开始,如getName()
松散耦合
应用的某个部分过于依赖于另一部分时,代码就是耦合过紧
解耦HTML/Javascript
直接写在HTML中的Javascript,使用包含内联代码的<script>
元素或者使用HTML属性来分配事件处理程序。例如:
<script type="text/javascript"> document.write("Hello world"); </script>
<input type="button" value="click me" onclick="doSomething()" />
或者javascript中包含HTML
container.innerHTML = "<div class='msg'><p class='post'>123</p></div>"
HTML应该尽可能与Javascript分离,当javascript用于插入标记时,尽量不要直接插入标记。一般可以在页面中包含标记并隐藏,等页面渲染后,再用javascript显示标记。或者进行Ajax请求获取要显示的HTML。
解耦CSS/Javascript
最常见的紧密耦合的例子是使用javascript来更改某些样式
element.style.color = "red";
应该尽可能地使用更改样式类而非特定的样式来实现
element.className = "edit";
解耦应用逻辑/事务处理程序
有些人将业务逻辑包含在事件处理程序中,例如
function handleKeyPress(event){
if (event.keyCode == 13){
var value = 5 * parseInt(event.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){
if (event.keyCode == 13){
validateValue(event.target.value);
}
}
编程实践
1 不要对不是你所有的对象有任何的修改
2 避免全局变量,最多创建一个全局变量吗,让其他对象和函数存在其中
var MyApplication = {
name: "zjw",
sayName: function(){
alert(this.name);
}
};
3 避免和null进行比较
- 如果值为一个引用类型,使用
instanceof
操作符检查其构造函数 - 如果值为一个基本类型,使用
typeof
检查类型 - 如果是希望对象包含某个特定的方法名,则使用
typeof
操作符确保指定名字的方法存在于对象上
4 使用常量
可以通过将数据抽取出来变成单独定义的常量,这样方便后期修改数据
var Constant = {
constant1:"value1",
constant2:"value2",
constant3:"value3"
};
定义为常量的数据类型常常包括以下几种:
- 重复的值:在多处地方用到的值
- 用户界面字符串:任何用于显示给用户的字符串,都应被抽取出来,方便国际化
- URLs:Web应用中,资源位置很容易变更,应使用一个公共地方存放所有URL
- 任意可能会更改的值
性能
1 避免全局查找
访问全局变量总要比访问局部变量慢,因为需要遍历作用域链
var doc = document; //保存document对象,不必多次重复查找
var imgs = doc.getElementsByTagName("img");
for (var i=0, len=imgs.length; i<len;i++){
imgs[i].title = doc.title + "image" + i;
}
var msg = doc.getElementById("msg");
msg.innerHTML = "update complete";
2 避免with语句
with语句会创建自己的作用域,增加其中执行代码的作用域长度
function updataBody(){
with(document.body){
alert(tagName);
innerHTML = "Hello world";
}
}
使用局部变量可以达到同样的效果,且代码更清晰
function updataBody(){
var body = document.body;
alert(body.tagName);
body.innerHTML = "Hello world";
}
3 避免双重解释
将包含Javascript代码的字符串,用作参数,会造成新启动一个解析器,下面的代码会造成这种情况
eval("alert('hello')");
var sayHi = new Function("alert('hello')");
setTimeout("alert('hello')",500);
除此之外,使用原生方法,用Switch
语句代替if-else
,使用位运算符都会提升代码的性能
最小化语句数
多个变量声明
使用一个var语句声明多个变量,用逗号隔开
var count = 5,
color = "blue",
values = [1,2,3],
now = new Date();
插入迭代值
var name = values[i++];
使用对象字面量
使用对象字面量的方式来创建对象及设置属性和方法,而不是创建对象后,再分别设置属性和方法的值
var person = {
name:"zjw",
age:29
};
优化DOM交互
使用文档片段
每一次DOM更改,都意味着性能的惩罚。因此要尽可能得减少DOM更新的次数
var list = document.getElementById("mylist"),
fragment = document.createDocumentFragment(), //创建文档片段
item,
i;
for (i=0;i<10;i++){
item = document.createElement("li");
fragment.appendChild(item);
item.appendChild(document.createTextNode("Item" + i));
}
list.appendChild(fragment); //插入文档片段
在这个例子中,只有一次DOM更新,就是在插入文档片段时,避免了多次插入列表项造成的性能损失。当给appendChild()
方法传入文档片段时,片段本身不会被添加,只会添加片段中的子节点
使用innerHTML
在进行大的DOM更改时,使用innerHTML比基于Javascript的DOM调用速度更快
使用事件委托
减少事件处理程序的数量,使用方法见 https://blog.csdn.net/zjw_python/article/details/79773871
注意HTMLCollection
任何时候访问HTMLCollection,不管是属性还是方法,都是在文档上一个查询,开销很大。因此要最小化访问HTMLCollection的次数
var images = document.getElementsByTagName("img"),
img,
i,len;
for (i=0; len = images.length; i < len; i++){
image = images[i]; //保存数据,避免对images的多次访问
//处理
}
发生以下情况会返回HTMLCollection
- 调用了
getElementsByTagName()
- 获取元素的
childNodes
属性 - 获取元素
attributes
属性 - 访问了特殊的集合,例如
document.images
或者document.forms
部署
在部署前推荐将Javascript合并为较少文件,并使用压缩器将文件尽可能变小,和HTTP压缩一起使用可以使JS文件变得更小。