懶人封裝(懶惰模式),實用小技巧
● 本文旨在一些特殊的封裝上
● 一般會用于處理瀏覽器兼容性的封裝
● 但是看完會對你有一些啟發也說不定哦 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:51
java全局變量
如果全局變量是一個對象,則可以更改該對象的狀態,即使變量本身是final類型。當一個方法被調用時,會為該方法在棧上分配一塊內存空間,用于存...詳情>>
2023-03-17 10:01:40
帶你手把手解決Java常見Bug
剛開始學習Java語言的小伙伴, 很可能被各種各樣的程序bug搞得焦頭爛額, 甚至被勸退。別怕,小編將手把手帶你了解Java中的異常體系, 如何識別Bug...詳情>>
2023-03-13 16:05:00
JavaScript 內的 this 指向
在 javascript 語言中, 有一個奇奇怪怪的 "關鍵字" 叫做 this詳情>>
2023-03-07 15:21:00