懒人封装(懒惰模式),实用小技巧
● 本文旨在一些特殊的封装上
● 一般会用于处理浏览器兼容性的封装
● 但是看完会对你有一些启发也说不定哦 O(∩_∩)O~
一段简单的代码
● 我们在封装 ajax 请求的时候
● 基于原生 js 的 ajax 代码, 如果考虑到浏览器兼容问题
● 那么我们一定会看到以下几段代码
// 标准浏览器下创建 ajax 对象
new XMLHttpRequest();
// 以下三种都是IE浏览器,对应不同版本
new ActiveXObject('Msxml12.XMLHTTP');
new ActiveXObject('Msxml13.XMLHTTP');
new ActiveXObject('Microsoft.XMLHTTP');
开始第一次封装
● 想到就做, 我们就来进行一次封装试试看
function xhl_ajax(options) {
// ...
let xml = null
if (window.XMLHttpRequest) {
xml = new XMLHttpRequest()
} else if (new ActiveXObject) {
xml = new new ActiveXObject('Microsoft.XMLHTTP')
} else {
xhl = '你的浏览器可能不支持 ajax 请求, 请更换浏览器再试'
}
// ...
}
● 我这里并没有写完整, 只是简单一个小示例
● 我们来分析一下这个事情
○ 我们的判断种类可能有很多种, 比如 A B C D 四种
// 那么这一段代码就变成了
function xhl_ajax() {
// ...
if (A) {
// ...
} else if (B) {
// ...
} else if (C) {
// ...
} else if (D) {
// ...
} else {
// ...
}
// ...
}
● 代码可能就变成了这个样子
● 可能有的小伙伴会想到, 我改成 策略模式 封装不就好了
我要说的不是这个问题
○ 不管你改成什么模式封装, 哪怕是起飞模式
○ 如果你当前需要匹配到的内容是 D
○ 那么每调用一次, 都会从 A 开始判断一次
○ 然后到达 D
// 第一次调用
xhl_ajax() // 需要判断 A 不对, B 不对, C 不对, D 对了
// 第二次调用
xhl_ajax() // 需要判断 A 不对, B 不对, C 不对, D 对了
// ...
● 想象一下, 如果调用了 100 次, 那么每次的前三个判断是不是都浪费了呢
● 好像是这样的
○ 那我们是不是可以考虑换一个方式来搞一下
懒惰模式封装这段代码
● 我们能不能考虑一下, 我封装完毕的代码, 只有第一次调用的时候会判断
● 后面调用的时候不在判断了, 那么是不是会节省很多呢 ?
● 想到就做
○ 原则就是多个事情依次完成
○ 前一个成功了, 后面的不做了
○ 只要成功过一次, 以后就不在尝试了
1. 把我们需要做的几个事情放在几个函数内
function createXHR1 () {
return new XMLHttpRequest;
}
function createXHR2 () {
return new XActiveXObject("Microsoft.XMLHTTP");
}
function createXHR3 () {
return new ActiveXObject("Msxml2.XMLHTTP");
}
function createXHR4 () {
return new ActiveXObject("Msxml3.XMLHTTP");
}
● 这样一来, 如果第一个能成功, 那么我们调用第一个函数就回得到对应的 ajax 对象了
● 如果第一个不行, 我们就尝试第二个
2. 接下来我们把四个函数放在一个数组内, 遍历依次执行
● 只要找到一个合适的就行了
var xmls = [createXHR1, createXHR2, createXHR3, createXHR4]
let xml = null
for (var i = 0; i < xmls.length; i++) {
// 一旦 xml 有内容了, 不再是 null 了, 那么直接结束循环
if (xml) break
// 否则就开始尝试
xml = xmls[i]()
}
● 问题随之而来了, 如果第一个不对, 那么会报错
● 我的代码就全部挂掉了
3. 尝试使用 try catch 解决问题
● 为了不让我的代码挂掉
● 我们改用 try catch 来解决问题
var xmls = [createXHR1, createXHR2, createXHR3, createXHR4]
let xml = null
for (let i = 0; i < xmls.length; i++) {
try {
xml = xmls[i]()
} catch(e) {}
}
● 错了也不需要做什么 , 直接下一次就好了
● 看上去挺好, 但是问题依旧没有解决
4. 单独制作一个函数
● 我的原则就是, 让这个函数第一次调用和第二次调用不是一个函数就好了
● 也就是我要在第一次调用完毕以后修改这个函数
function createXHR() {
// 定义一个 xhr 接收 ajax 对象
// 定义一个 flag 开关,看看是否找到合适的创建 ajax 对象的方法
// 定义一个数组,存储四种创建 ajax 对象的方式
let xml = null,
flag = false,
xmls = [
function () {
return new XMLHttpRequest;
},
function () {
return new ActiveXObject("Microsoft.XMLHTTP");
},
function () {
return new ActiveXObject("Msxml2.XMLHTTP");
},
function () {
return new ActiveXObject("Msxml3.XMLHTTP");
}
];
// 依旧是循环遍历数组
for (let i = 0, len = xmls.length; i < len; i++) {
let curFn = ary[i];
// 依次执行,找到合适的创建 ajax 对象的方法
try {
xml = curFn();
// 这里是核心,一旦找到合适的方法,那么我们就把这个函数重新赋值给 createXHR
createXHR = curFn;
// 让开关为 true
flag = true;
break;
} catch (e) {
}
}
// 如果到最后开关依旧为 false,证明四种方法都不合适,那么我们就需要提醒浏览器升级
if (!flag) {
throw new Error("your browser is not support ajax, please change your browser,try again!");
}
// 最后返回 ajax 对象
return xml;
}
● 看似没有什么改变,但是之一第 28 行的代码,有一个重写 createXHR
● 这个是整个”惰性思想”的核心,也就是说,我只有在当前浏览器中,第一次执行 createXHR 的时候是这个函数
● 一旦找到一个合适的创建 ajax 对象的方法以后,那么从第二次执行 createXHR 开始,就全部都是我们之前数组中的某一个函数了
● 再也不用循环判断,而是直接用一种有效的方法创建一个 ajax 对象了
● 这个是一种 js 中的高级编程思想,如果理解不了,就用我们最开始写的判断的形式来进行就可以,慢慢体会一段时间就能明白了
完整代码
function createXHR() {
let xml = null,
flag = false,
xmls = [
function () {
return new XMLHttpRequest;
},
function () {
return new ActiveXObject("Microsoft.XMLHTTP");
},
function () {
return new ActiveXObject("Msxml2.XMLHTTP");
},
function () {
return new ActiveXObject("Msxml3.XMLHTTP");
}
];
for (let i = 0, len = xmls.length; i < len; i++) {
let curFn = ary[i];
try {
xml = curFn();
createXHR = curFn;
flag = true;
break;
} catch (e) {
}
}
if (!flag) {
throw new Error("your browser is not support ajax, please change your browser,try again!");
}
return xml;
}
function xhl_ajax(options) {
// ...
const xml = createXHR()
// ...
}
● 从此以后, 你就去随便调用吧
● 只有第一次的时候会进行判断, 后面的时候都不会进行判断了
● 直接就能使用那个最准确的了
相关推荐HOT
更多>>xml解析器
SAX解析器:基于事件驱动的解析器,逐行读取XML文件并触发相应的事件,适用于处理大型XML文件,但需要手动编写事件处理器来处理XML文件中的数据...详情>>
2023-03-21 16:03:51java全局变量
如果全局变量是一个对象,则可以更改该对象的状态,即使变量本身是final类型。当一个方法被调用时,会为该方法在栈上分配一块内存空间,用于存...详情>>
2023-03-17 10:01:40带你手把手解决Java常见Bug
刚开始学习Java语言的小伙伴, 很可能被各种各样的程序bug搞得焦头烂额, 甚至被劝退。别怕,小编将手把手带你了解Java中的异常体系, 如何识别Bug...详情>>
2023-03-13 16:05:00JavaScript 内的 this 指向
在 javascript 语言中, 有一个奇奇怪怪的 "关键字" 叫做 this详情>>
2023-03-07 15:21:00