高质量的JavaScript
参考书籍《Web前端开发修炼之道》
控制全局变量,避免冲突隐患
1.匿名函数
将脚本用匿名函数包起来,作用域不在是window,而局限在函数内;
<script type="text/javascript">
(function() {
var a=123,b="mytest";
})()
</script>
<script type="text/javascript">
(function() {
var a,c="mytest";
})()
</script>
匿名函数之间通信问题
在window作用域下定义全局变量,作为它们之间的桥梁,但是这样违反了“控制全局变量,避免冲突”的初衷,如何正确定义全局变量?
使用**{}**对象类型的变量作为全局变量,对象里面再定义需要使用的若干变量或若干层级的变量。通常全局变量名称可取为:GLOBAL
<script type="text/javascript">
var GLOBAL={};
</script>
<script type="text/javascript">
(function(){
var a=123,b="mytest";
var GLOBAL.A={};
GLOBAL.A.str1="test1";//多级命名空间,实现对代码块A的变量唯一定义
GLOBAL.A.str2="test2";
})()
</script>
<script type="text/javascript">
(function(){
var a,c="abc";
var GLOBAL.B={};
GLOBAL.A.str1="test3";//多级命名空间,实现对代码块B的变量唯一定义
GLOBAL.A.str2="test4";
})()
</script>
生成命名函数封装
<script type="text/javascript">
var GLOBAL={};
GLOBAL.namespace=function(str){
var arr=str.split(".");
for(var i=(arr[0]=="GLOBAL")?1:0;i<arr.length;i++){
GLOBAL[arr[i]]=GLOBAL[arr[i]] || {};
GLOBAL=GLOBAL[arr[i]];
}
}
</script>
<script type="text/javascript">
(function(){
var a=123,b="mytest";
GLOBAL.namespace("A.test1");
GLOBAL.namespace("B.test2");
GLOBAL.A.test1.one="aa";
GLOBAL.B.test2.two="bb";
})
</script>
2.代码注释
无论是个人开发还是多人开发,代码注释都有助于当时开发速度和后续修改及追溯
注释可包含:功能说明、开发者姓名、开发者联系方式、代码最后修改时间等
3.给程序统一入口
给程序统一入口,即把零散的js代码,集中放在init(习惯性取名)函数里。
4.页面加载顺序问题
a.css放在页头,在载入html之前先加载样式,避免html出现无样式状态
b.js放在页尾标签之后,避免js阻塞网页的呈现,减少页面空白的时间
如果程序内有引入如jquery之类的框架,可利用其封装的DOMReady方法,装js代码包里面
function init(){
}
$(function(){
init
})
或
$(document).ready(init)
拓展:
window.onload与一些js提供的DOMReady区别
window.onload:当前页面全部加载完毕后才触发,包括图片、flash等富媒体
DOMReady:Dom节点加载完毕就执行,不用管节点内的内容有无加载好
5.文件压缩
文件压缩需要借助一些压缩插件;
js压缩通常的做法是去掉空格与注释,将复杂变量名替换为简单变量名;
压缩文件与源文件命名需要有关联及对立性,如
jquey.js 与 juqey-min.js
6.js分层概念
js分层即将js代码按功能分类,形成不同的js文件
例如:
a.最底层(base层):
职责一:封装不同浏览器下js的差异,提供统一接口
职责二:扩展js语言一些方法,使其有更多易用的接口
b.中间层(common层):
依赖于base层提供的接口
职责:提供可供复用的组件,和页面上具体的功能没有直接关系
c.页面层(page层):
依赖base层与comon层
职责:完成页面内的功能需求
base层扩展js方法,举例:
function isArray(s){//判断是否为数组
return s instanceof Array;
}
function isFunction(s){
return typeof s==="function";
}
function trim(str){
retrun str.replace(/\s+/g,"");
}
如比较有名的js扩展库underscore.js
(https://underscorejs.org)
common层封装组件,举例:
对cookie的封装
GLOBAL.namespace("cookie");
GLOBAL.Cookie={
getCookie:function(name){
var cookie_str="; "+document.cookie+"; ";
var index=cookie_str.indexOf("; "+name+"=");
if(index!=-1){
var arr = cookie_str.split("; ");
for(var i = 0; i < arr.length; i++){
//console.log(arr[i]);
var newArr = arr[i].split("=");
if(newArr[0]==name){
return newArr[1];
}
}
}else{
return null;
}
};
setCookie(name,value,n){
var oDate = new Date();
oDate.setDate(oDate.getDate()+n);
document.cookie = name+"="+value+";expires="+oDate;
}
delete:function(){
setCookie(name,1,-1);
}
}
很多开源的javascript库为我们提供了强大的的base层和common层,例如我们最为熟知的jQuery;
jQuery本身分为两大部分:jQuery核心文件和jQuery UI文件,jQuery UI文件依赖jQuery核心文件。
对DOM和Event相关方法的封装,如:
(
)
.
f
i
n
d
(
)
、
().find()、
().find()、().on();对原生Javascript语言底层的扩展,如:$.inArray();动画和Ajax功能。jQuery UI提供大量常用功能,如:Drag、Resize、Tab等。
jQuery核心文件提供了base层功能,部分common层功能;jQuery UI文件提供了common层功能。
组件编写
编写组件是件非常考验工程师能力的事,一个高品质的组件需具备以下几点:
1.跨浏览器兼容;
2.组件易用;
3.组件可重用;
4.组件可扩展;
5.代码组织有序,高内聚低耦合