你只需要检查一个元素是否存在,而不需要检查每个元素
你可以动态地添加或者删除子节点而并不需要删除相应的事件处理器
你可以在不同的元素上对相同的事件做出响应
需要记住的另一件事是,在事件向父元素传播的时候你可以停止它而且你可以覆写掉HTML元素(比如链接)的缺省行为。不过,有时候这并不是个好主意,因为浏览器赋予HTML元素那些行为是有原因的。举个例子,链接可能会指向页面内的某个目标,不去修改它们能确保用户可以将页面当前的脚本状态也加入书签。
6.为他人着想(命名空间,作用域和模式)
你的代码几乎从来不会是文档中的唯一的脚本代码。所以保证你的代码里没有其它脚本可以覆盖的全局函数或者全局变量就显得尤为重要。有一些可用的模式可以来避免这个问题,最基础的一点就是要使用 var 关键字来初始化所有的变量。假设我们编写了下面的脚本:
var nav = document.getElementById('nav');
function init(){
// do stuff
}
function show(){
// do stuff
}
function reset(){
// do stuff
}
上面的代码中包含了一个叫做nav的全局变量和名字分别为 init,show 和 reset 的三个函数。这些函数都可以访问到nav这个变量并且可以通过函数名互相访问:
var nav = document.getElementById('nav');
function init(){
show();
if(nav.className === 'show'){
reset();
}
// do stuff
}
function show(){
var c = nav.className;
// do stuff
}
function reset(){
// do stuff
}
你可以将代码封装到一个对象中来避免上面的那种全局式编码,这样就可以将函数变成对象中的方法,将全局变量变成对象中的属性。 你需要使用“名字+冒号”的方式来定义方法和属性,并且需要在每个属性或方法后面加上逗号作为分割符。
var myScript = {
nav:document.getElementById('nav'),
init:function(){
// do stuff
},
show:function(){
// do stuff
},
reset:function(){
// do stuff
}
}
所有的方法和属性都可以通过使用“类名+点操作符”的方式从外部和内部访问到。
var myScript = {
nav:document.getElementById('nav'),
init:function(){
myScript.show();
if(myScript.nav.className === 'show'){
myScript.reset();
}
// do stuff
},
show:function(){
var c = myScript.nav.className;
// do stuff
},
reset:function(){
// do stuff
}
}
这种模式的缺点就是,你每次从一个方法中访问其它方法或属性都必须在前面加上对象的名字,而且对象中的所有东西都是可以从外部访问的。如果你只是想要部分代码可以被文档中的其他脚本访问,可以考虑下面的模块(module)模式:
var myScript = function(){
//这些都是私有方法和属性
var nav = document.getElementById('nav');
function init(){
// do stuff
}
function show(){
// do stuff
}
function reset(){
// do stuff
}
//公有的方法和属性被使用对象语法包装在return 语句里面
return {
public:function(){
},
foo:'bar'
}
}();
你可以使用和前面的代码同样的方式访问返回的公有的属性和方法,在本示例中可以这么访问:myScript.public() 和 myScript.foo 。但是这里还有一点让人觉得不舒服:当你想要从外部或者从内部的一个私有方法中访问公有方法的时候,还是要写一个冗长的名字(对象的名字可以非常长)。为了避免这一点,你需要将它们定义为私有的并且在return语句中只返回一个别名:
var myScript = function(){
// 这些都是私有方法和属性
var nav = document.getElementById('nav');
function init(){
// do stuff
}
function show(){
// do stuff
// do stuff
}
function reset(){
// do stuff
}
var foo = 'bar';
function public(){
}
//只返回指向那些你想要访问的私有方法和属性的指针
return {
public:public,
foo:foo
}
}();
这就保证了代码风格一致性,并且你可以使用短一点的别名来访问其中的方法或属性。
如果你不想对外部暴露任何的方法或属性,你可以将所有的代码封装到一个匿名方法中,并在它的定义结束后立刻执行它:
(function(){
// these are all private methods and properties
var nav = document.getElementById('nav');
function init(){
// do stuff
show(); // 这里不需要类名前缀
}
function show(){
// do stuff
}
function reset(){
// do stuff
}
})();
对于那些只执行一次并且对其它函数没有依赖的代码模块来说,这种模式非常好。
通过遵循上面的那些规则,你的代码更好地为用户工作,也可以使你的代码在机器上更好地运行并与其他开发者的代码和睦相处。不过,还有一个群体需要考虑到。
7.为接手的开发者考虑(使维护更加容易)
使你的脚本真正地unobtrusive的最后一步是在编写完代码之后仔细检查一遍,并且要照顾到一旦脚本上线之后要接手你的代码的开发者。考虑下面的问题:
所有的变量和函数名字是否合理并且易于理解?
代码是否经过了合理的组织?从头到尾都很流畅吗?
所有的依赖都显而易见吗?
在那些可能引起混淆的地方都添加了注释吗?
最重要的一点是:要认识到文档中的HTML和CSS代码相对于JavaScript来说更有可能被改变(因为它们负责视觉效果)。所以不要在脚本代码中包含任何可以让终端用户看到的class和ID,而是要将它们分离出来放到一个保存配置信息的对象中。