學(xué)習(xí)JavaScript設(shè)計(jì)模式之代理模式
- 明星都有經(jīng)紀(jì)人作為代理。如果請(qǐng)明星辦一場(chǎng)商演,只能聯(lián)系其經(jīng)紀(jì)人,經(jīng)紀(jì)人會(huì)把商演的細(xì)節(jié)和報(bào)酬談好,再把合同交給明星簽。
一、定義
代理模式:為一個(gè)對(duì)象提供一個(gè)代用品或占位符,以便控制對(duì)它的訪問(wèn)。
代理分為:保護(hù)代理和虛擬代理
保護(hù)代理:用于控制不同權(quán)限的對(duì)象對(duì)目標(biāo)對(duì)象的訪問(wèn),在JavaScript中很難判斷誰(shuí)訪問(wèn)了某個(gè)對(duì)象,所以保護(hù)代理很難實(shí)現(xiàn)。
二、圖片預(yù)加載(最常見(jiàn)的虛擬代理應(yīng)用場(chǎng)景)
圖片預(yù)加載是一種常用技術(shù),如果直接給某個(gè)img標(biāo)簽節(jié)點(diǎn)設(shè)置src屬性,由于圖片過(guò)大或者網(wǎng)絡(luò)不佳,圖片的位置往往有段時(shí)間會(huì)有空白。常見(jiàn)的做法事先用一張loading圖片占位,然后異步加載圖片,待圖片加載完成,把其填充到img節(jié)點(diǎn)里。
實(shí)現(xiàn)原理:
創(chuàng)建一個(gè)Image對(duì)象:var a = new Image();
定義Image對(duì)象的src: a.src = “xxx.gif”;
這樣做就相當(dāng)于給瀏覽器緩存了一張圖片。
可通過(guò)Image對(duì)象的complete屬性來(lái)檢測(cè)圖像是否加載完成。每個(gè)Image對(duì)象都有一個(gè)complete屬性,當(dāng)圖像處于裝載過(guò)程中時(shí),該屬性值false,當(dāng)發(fā)生了onload、onerror、onabort中任何一個(gè)事件后,則表示圖像裝載過(guò)程結(jié)束,此時(shí)complete屬性為true。
(1)非代理實(shí)現(xiàn)
var myImage = (function() { var imgNode = document.createElement("img"); document.body.appendChild(imgNode); var img = new Image(); img.onload = function() { imgNode.src = img.src; }; return { setSrc: function(src) { imgNode.src = "./images/loading.gif"; img.src = src; } } })(); myImage.setSrc("./images/originImg.png");
(2)代理實(shí)現(xiàn)
// 創(chuàng)建圖片DOM var myImage = (function() { var imgNode = document.createElement("img"); document.body.appendChild(imgNode); return { setSrc: function(src) { imgNode.src = src; } }; })(); // 代理 var proxyImage = (function() { var img = new Image(); img.onload = function() { myImage.setSrc(this.src); // this指向img!img加載完成后,將img.src傳遞給myImage }; return { setSrc: function(src) { myImage.setSrc("./images/loading.gif"); // loading img.src = src; } }; })(); proxyImage.setSrc("./images/originImg.png");
使用代理模式的好處:使每個(gè)函數(shù)功能單一,實(shí)現(xiàn)對(duì)象設(shè)計(jì)的“單一職責(zé)原則”!
三、文件同步
假設(shè)我們?cè)谧鲆粋€(gè)文件同步功能,當(dāng)選中checkbox時(shí)候,它對(duì)應(yīng)的文件就會(huì)被同步到另外一臺(tái)服務(wù)器。
<body> <input type="checkbox" id="1" />文件1 <input type="checkbox" id="2" />文件2 <input type="checkbox" id="3" />文件3 <input type="checkbox" id="4" />文件4 <input type="checkbox" id="5" />文件5 <input type="checkbox" id="6" />文件6 </body>
沒(méi)選中一個(gè)checkbox就同步一次,顯然不太合理。因?yàn)樵趙eb開(kāi)發(fā)中,最大的開(kāi)銷就是網(wǎng)絡(luò)請(qǐng)求。
解決方案:通過(guò)一個(gè)代理函數(shù)來(lái)收集一段時(shí)間之內(nèi)的請(qǐng)求,然后一次性發(fā)給服務(wù)器。
var synchronousFile = function(id) { console.log("開(kāi)始同步文件,id為:" + id); }; var proxySynchonousFile = (function() { var cache = [], // 保存本次需要同步文件的id timer; // 定時(shí)器 return function(id) { cache.push(id); if(timer) { // 不要覆蓋已經(jīng)啟動(dòng)的定時(shí) return; } timer = setTimeout(function(){ synchronousFile(cache.join(",")); clearTimeout(timer); timer = null; cache.length = 0; // 清空緩存 }, 2000); } })(); var checkboxs = document.getElementsByTagName("input"); for(var i = 0, c; c = checkboxs[i]; i++) { c.onclick = function() { if(this.checked === true) { proxySynchonousFile(this.id); } } }
四、緩存代理–計(jì)算乘積(序列一模一樣)
var mult = function() { var result = 1; for(var i = 0, l = arguments.length; i < l; i++) { result= result * arguments[i]; } return result; }; var proxyMult = (function() { var cache = {}; // {"1,2,3": 6} return function() { var args = Array.prototype.join.call(arguments, ","); if(args in cache) { return cache[args]; } return cache[args] = mult.apply(this, arguments); } })(); console.log(proxyMult(1, 2, 3)); // 改造: var proxyFactory = function(fn) { var cache = {}; return function() { var args = Array.prototype.join.call(arguments, ","); if(args in cache) { return cache[args]; } return cache[args] = fn.apply(this, arguments); } }; console.log(proxyFactory(mult)(1, 2, 3));
希望本文所述對(duì)大家學(xué)習(xí)javascript程序設(shè)計(jì)有所幫助。
- javascript設(shè)計(jì)模式 – 代理模式原理與用法實(shí)例分析
- js設(shè)計(jì)模式之代理模式及訂閱發(fā)布模式實(shí)例詳解
- 詳解javascript設(shè)計(jì)模式三:代理模式
- JavaScript設(shè)計(jì)模式之代理模式實(shí)例分析
- JavaScript設(shè)計(jì)模式之緩存代理模式原理與簡(jiǎn)單用法示例
- JavaScript設(shè)計(jì)模式之代理模式簡(jiǎn)單實(shí)例教程
- JavaScript設(shè)計(jì)模式之代理模式詳解
- JavaScript的設(shè)計(jì)模式經(jīng)典之代理模式
- 學(xué)習(xí)JavaScript設(shè)計(jì)模式(代理模式)
- 深入理解JavaScript系列(31):設(shè)計(jì)模式之代理模式詳解
- JavaScript設(shè)計(jì)模式之代理模式介紹
- JavaScript設(shè)計(jì)模式學(xué)習(xí)之代理模式
相關(guān)文章
使用Taro實(shí)現(xiàn)小程序商城的購(gòu)物車功能模塊的實(shí)例代碼
這篇文章主要介紹了使用Taro實(shí)現(xiàn)的小程序商城的購(gòu)物車功能模塊,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06js實(shí)現(xiàn)動(dòng)態(tài)添加上傳文件頁(yè)面
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)動(dòng)態(tài)添加上傳文件頁(yè)面,如何動(dòng)態(tài)創(chuàng)建一個(gè)input標(biāo)簽示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-10-10input標(biāo)簽內(nèi)容改變的觸發(fā)事件介紹
onchange事件在內(nèi)容改變(兩次內(nèi)容有可能相等)且失去焦點(diǎn)時(shí)觸發(fā);onpropertychange事件是實(shí)時(shí)觸發(fā),每增加或刪除一個(gè)字符就會(huì)觸發(fā)2014-06-06微信小程序?qū)崿F(xiàn)點(diǎn)擊出現(xiàn)彈窗
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)點(diǎn)擊出現(xiàn)彈窗,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07JavaScript判斷數(shù)組的方法總結(jié)與推薦
這篇文章主要給大家介紹了關(guān)于JavaScript判斷數(shù)組方法的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-02-02JavaScript實(shí)現(xiàn)的XML與JSON互轉(zhuǎn)功能詳解
這篇文章主要介紹了JavaScript實(shí)現(xiàn)的XML與JSON互轉(zhuǎn)功能,結(jié)合實(shí)例形式分析了基于javascript的xml與json相關(guān)轉(zhuǎn)換功能實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-02-02Javascript前端事件循環(huán)機(jī)制詳細(xì)講解
單線程的同步等待極大影響效率,任務(wù)不得不一個(gè)一個(gè)等待執(zhí)行,對(duì)于網(wǎng)頁(yè)應(yīng)用是無(wú)法接受的。所以Javascript使用事件循環(huán)機(jī)制來(lái)解決異步任務(wù)的問(wèn)題。本文就來(lái)講講Javascript的事件循環(huán)機(jī)制,希望對(duì)你有所幫助2022-12-12