示例一
为某个元素注册一个事件,提供事件的处理函数
存在的问题
function addEvent(ele, eventName, handler) {
if (ele.addEventListener) {
ele.addEventListener(eventName, handler);
} else if (ele.attachEvent) {
ele.attachEvent('on'+eventName, handler);
} else {
ele['on'+eventName] = handler;
}
}
- 函数内部处理了浏览器的兼容性问题
- 每次调用该方法注册事件的时候,都需要经过一系列的判断,实际上是没有必要的
- 用户的浏览器环境是确定的,到底支持哪一种事件注册方式在最开始的时候就可以确定下来
优化
var addEvent = (function () {
if (ele.addEventListener) {
return function (ele, eventName, handler) {
ele.addEventListener(eventName, handler);
}
} else if (ele.attachEvent) {
return function (ele, eventName, handler) {
ele.attachEvent('on'+eventName, handler);
}
} else {
return function (ele, eventName, handler) {
ele['on'+eventName] = handler;
}
}
})()
- 使用立即执行函数,把判断放到立即执行函数里面,这些判断在最开始的时候就会运行,而不用等到调用该函数的时候才执行
- 在每个分支里面,为每个环境返回特定的事件注册函数,将来用户使用的时候直接就使用特定环境的时间注册函数
示例二
发送请求,适配浏览器环境和node环境
function request (options) {
if (typeof window !== 'undefined') {
// 浏览器环境的ajax
} else {
// node环境
}
}
- 到底是浏览器环境还是node环境在最开始就能确认,不用等到调用的时候才去进行判断
var request = (function(){
if (typeof window !== 'undefined') {
// 浏览器环境的ajax
return (options) => {}
} else {
// node环境
return (options) => {}
}
})()
示例三
存在的问题
function removeSpace (str) {
var regexep = /\s/g;
return str.replace(regexep, '');
}
- 正则是一个对象肯定会占用内存空间
- 不起眼的空字符串仍然会占用内存空间
- 每次调用该函数都会重新生成正则对象,和一个空字符串,都会占用内存,
- 如果调用该函数的次数变多了,会发现内存占用的曲线图是波动很大, 忽上忽下;函数的执行期间就会上升,函数结束完成后到达某个垃圾回收的时间点,它内存就会下降,因为内存会被回收;下次调用的时候会升高又会下降
- 不能保证函数内部占用的内存很少,如果占用的很多就会出现问题
- 内存忽上忽下带来的开销是很大的
优化
立即执行函数
var removeSpace = (function() {
var regexep = /\s/g;
return (str) => str.replace(regexep, '');
})()
- 正则对象只会占用一份内存空间,下次调用不会重新分配内存空间;内存不会忽上忽下
- 想释放内存的时候,不能removeSpace = null,否则该函数就不能使用了
- 但是问题是:正则对象受到了闭包的影响,它会全局的长久的停留到内存空间里面
高阶函数
var createRemoveSpace = function() {
var regexep = /\s/g;
return (str) => str.replace(regexep, '');
}
var removeSpace = createRemoveSpace();
removeSpace('abc');
removeSpace('def');
removeSpace('ghx');
removeSpace = null;
- 把立即执行函数改成高阶函数
- 不是立即执行函数说有在没有执行之前不会占用内存空间
- 在第一次调用的时候才会生成占用内存的正则对象
- 第二次调用正则对象只会占用一份内存空间,内存占用会比较平稳,不会忽上忽下
- 当不再使用removeSpace函数时候就把其设置为null,该函数就会被垃圾回收,然后高阶函数依赖的正则对象也就会垃圾回收期回收,不会永久驻留到内存中