惰性模式

惰性模式: 减少每次代码执行时的重复性的分支判断, 通过对对象重定义来屏蔽原对象中的分支判断.

问题

为了兼容旧版浏览器, 我们往往会封装一些方法. 其中不可避免的会用到一些条件判断. 这些判断在同一个浏览器中就显得很多余. 比如下面的绑定事件的封装

1
2
3
4
5
6
7
8
9
10
11
12
function addEvent(dom, type, fn) {
// 对于支持DOM2级事件处理程序addEventListener方法的浏览器
if (dom.addEventListener) {
dom.addEventListener(type, fn, false)
} else if (dom.attachEvent) {
// 对于不支持addEventListener方法 但支持attachEvent方法的浏览器
dom.attachEvent('on' + type, fn)
} else {
// 对于不支持addEventListener 也不支持attachEvent, 但支持on+'事件名的浏览器
dom['on' + type] = fn
}
}

我们可以通过重定义的方式, 在初始时执行判断浏览器环境, 然后对函数重定义, 解决代码中的对浏览器重复性功能校验.

解决方案

惰性模式一般有两种实现思路

  • 第一种, 在文件加载进来时通过闭包执行该方法对其重新定义. 不过这样会使页面加载时占用一定资源.
  • 第二种, 在函数第一次调用时对其重定义, 好处是减少文件加载时的资源消耗, 按需执行.

加载即执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var A = {}
A.on = (function (dom, type, fn) {
// 如果支持addEventListener方法
if (document.addEventListener) {
// 返回新定义方法
return function (dom, type, fn) {
dom.addEventListener(type, fn, false)
}
} else if (document.attachEvent) {
return function (dom, type, fn) {
dom.attachEvent('on' + type, fn)
}
} else {
return function (dom, type, fn) {
dom['on' + type] = fn
}
}
})()

惰性执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var A = {}
A.on = function (dom, type, fn) {
if (dom.addEventListener) {
A.on = function (dom, type, fn) {
dom.addEventListener(type, fn, false)
}
} else if (dom.attachEvent) {
A.on = function (dom, type, fn) {
dom.attachEvent('on' + type, fn)
}
} else {
A.on = function (dom, type, fn) {
dom['on' + type] = fn
}
}
// 执行重定义on方法
A.on(dom, type, fn)
}

其他常见的兼容方法

获取事件对象

1
2
3
4
var getEvent = function (event) {
// 标准浏览器返回event, IE 下 window.event
return event || window.event
}

获取元素

1
2
3
4
5
var getTarget = function (event) {
var event = getEvent(event)
// 标准浏览器下 event.target, IE下event.srcElement
return event.target || event.srcElement
}

阻止默认行为

1
2
3
4
5
6
7
8
9
var preventDefault = function (event) {
var event = getEvent(event)
// 标准浏览器
if (event.preventDefault) {
event.preventDefault()
} else {
event.returnValue = false
}
}