编程实践
1.将JavaScript从CSS中抽离
要避免使用CSS表达式
2.将CSS从JavaScript中抽离
最好使用JavaScript操作CSS的classname,而不要直接更改.style
3.将JavaScript从HTML中抽离
最好不要在HTML中使用on属性来绑定一个事件处理程序,最好将所有的JavaScript代码放入外置文件中,以确保在HTML代码中不会有内联的JavaScript代码
4.全局变量会带来的问题
(1) 命名冲突
(2) 代码的脆弱性
(3) 难以测试
name实际上市window的一个默认属性。window.name属性经常勇于frame和iframe的场景中,当点击链接时,可以通过指定打开链接的目标容器来控制其在特定的框架或选项卡中显示,不小心修改name会影响到站点的链接导航。
5.使用命名空间
var YourGlobal = {
namespace: function(ns) {
var parts = ns.split("."),
object = this,
i,
len;
for(i = 0, len = parts.length; i != len; i++) {
if (!obejct[parts[i]]) {
object[parts[i]] = {};
}
object = object[parts[i]];
}
return object;
}
}
/*
*同时创建YourGlobal.Books和YourGloabl.Books.MaintainableJavaScript
*因为之前没有创建过它们,因此每个都是全新创建的
*/
YourGlobal.namespace("Books.MaintainableJavaScript");
//现在你可以使用这个命名空间
YourGlobal.Books.MaintainableJavaScript.author = "Raul";
/*
*不会操作YourGlobal.Books本身,同时会给它添加HighPerformanceJavaScript
*它会保持YourGlobal.Books.MaintainableJavaScript原封不动
*/
YourGlobal.namespace("Books.HighPerformanceJavaScript");
//仍然是合法的引用
console.log(YourGlobal.Books.MaintainableJavaScript.author);
//你同样可以在方法调用之后立即给它添加新属性
YourGlobal.namespace("Books").ANewBook = {};
6.模块
YUI.add("module-name", function(Y) {
//body
}, "version", { requires: ["dependency1", "dependency2"]});
YUI().use("module-name1", "module-name2", function(Y) {
//body
});
7.AMD:异步模块定义
AMD模块和YUI模块最大的不同在于,(AMD中)每一个依赖都会对应到独立的参数传入工厂方法里,比如:
define("module-name", ["dependency1", "dependency2"],
function(dependency1, dependency2) {
//body
});
8.事件处理
规则1:隔离应用逻辑
规则2:不要分发事件对象
9.将配置数据从代码中分离出来//不好的写法 function handleClick(event) { var popup = document.getElementById("popup"); popup.style.left = event.clientX + "px"; popup.style.top = event.clientY + "px"; popup.className = "reveal"; } addListener(element, "click", handleClick); //好的做法 var MyApplication = { handleClick: function(event) { //假设事件支持DOM Level2 event.preventDefault(); event.stopPropagation(); //传入应用逻辑 this.showPopup(event.clientX, event.clientY); } showPopup: function(x, y) { var popup = document.getElementById("popup"); popup.style.left = x + "px"; popup.style.top = y + "px"; popup.className = "reveal"; } } addListener(element, "click", function(event) { MyApplication.handleClick(event); })
配置数据的一些例子:
- URL
- 需要展现给用户的字符串
- 重复的值
- 设置(比如每页的配置项)
- 任何可能发生变更的值
- 一旦修复了一个很难调试的错误,尝试添加一两个自定义错误,当再次发生错误时,这将有助于更容易地解决问题
- 如果正在编码,思考一下:“我希望[某些事情]不会发生,如果发生,我的代码会一团糟糕”。这时,如果“某些事情”发生,就抛出一个错误
- 如果正在编写的代码别人也会使用,思考一下他们使用的方式,在特定的情况下抛出错误
11.错误类型
- Error:错误的基本类型,但从不会抛出
- EvalError:通过eval()函数执行代码发生错误抛出
- RangeError
- ReferenceError:期望的对象不存在时抛出
- SyntaxError:有语法错误
- TypeError:类型不符
- URIError:给encodeURI(),encodeURIComponent(),decodeURI()和decodeURIComponent()等函数传递非法的URI时抛出
13.尽可能地使用特性检测,如果不能这么做的时候,可以退而求其次,考虑用户代理检测,永远不要使用浏览器推断,因为你会被这样维护性很差的代码缠身,而且随着新的浏览器的出现,需要不断地更新代码。