日期:2014-05-16  浏览次数:20326 次

JavaScript学习笔记(十六) 初始化时分支

初始化时分支(Init-Time Branching)

初始化时分支(也叫做载入时分支(load-time branching))是一种优化的模式;
当你知道某一个明确的条件在整个程序生命周期中都不会发生改变,那么只判断这一次条件就会变的有意义;
浏览器嗅探(Browser sniffing)(或者功能探测(feature detection)))都是典型的例子。

比如,当你已经嗅探到XMLHttpRequest被作为一个原生对象而支持;
那么在整个程序执行的过程中,相关联的浏览器是没有机会改变的,你不会突然被要求去处理ActiveX对象;
因为环境没有改变,所以没有理由让的代码在你每次需要一个XHR对象是都进行嗅探(并得到相同的结论)。

附加事件监听器程序也可以从初始化时分支模式获益,绝大部分程序猿都写过——在他们的客户端编程人生中至少写过一次——一个工具;
具有附加和移除事件监听器方法,像下面:
// BEFORE
var utils = {
addListener: function (el, type, fn) {
if (typeof window.addEventListener === 'function') {
el.addEventListener(type, fn, false);
} else if (typeof document.attachEvent === 'function') { // IE
el.attachEvent('on' + type, fn);
} else { // older browsers
el['on' + type] = fn;
}
},
removeListener: function (el, type, fn) {
// pretty much the same...
}
};
这段代码的问题是低效的,因为每次当你调用utils.addListener() 或 utils.removeListener()的时候,相同的检查就会一次又一次被执行;

使用初始化时分支,你只需要在脚本载入的过程中嗅探一次浏览器的特征,在这个时候你可以重定义函数行为;
下面是个例子,如何实现这个任务:
// AFTER
// the interface
var utils = {
addListener: null,
removeListener: null
};
// the implementation
if (typeof window.addEventListener === 'function') {
utils.addListener = function (el, type, fn) {
el.addEventListener(type, fn, false);
};
utils.removeListener = function (el, type, fn) {
el.removeEventListener(type, fn, false);
};
} else if (typeof document.attachEvent === 'function') { // IE
utils.addListener = function (el, type, fn) {
el.attachEvent('on' + type, fn);
};
utils.removeListener = function (el, type, fn) {
el.detachEvent('on' + type, fn);
};
} else { // older browsers
utils.addListener = function (el, type, fn) {
el['on' + type] = fn;
};
utils.removeListener = function (el, type, fn) {
el['on' + type] = null;
};
}

接下来是一些关于使用浏览器嗅探的警告,当你使用这种模式,不要过分假设浏览器的功能;
比如:你已经嗅探到浏览器不支持window.addEventListener,不要仅仅假设你正在应对的浏览器就是IE,而且它也不支持原生的XMLHttpRequest;
也有一些情况你可以安全的假设功能是想对应,比如.addEventListener和 .removeEventListener;
但是一般来说浏览器功能改变是独立的,最好的策略是去单独嗅探功能然后再使用载入时分支模式仅仅只做一次嗅探。