爲一個對象提供一個代用品或佔位符,以便控制對它的訪問。緩存
當客戶不方便直接訪問一個對象的時候,須要提供一個替身對象來控制對這個對象的訪問。app
替身對象對請求作出一些處理以後, 再把請求轉交給本體對象。函數
代理模式共有三種:保護代理、虛擬代理、緩存代理this
保護代理:spa
用於控制不一樣權限的對象對目標權限的訪問,實現訪問訪問主題的控制行爲。prototype
// 主體,發送消息 function sendMsg(msg) { console.log(msg); } // 代理,對消息進行過濾 function proxySendMsg(msg) { // 無消息則直接返回 if (typeof msg === 'undefined') { console.log('No Msg'); return; } // 有消息則進行過濾 msg = "收到的msg是:" + msg; sendMsg(msg); } sendMsg("msg1"); // msg1 proxySendMsg('msg2'); // 收到的msg是:msg2 proxySendMsg(); // No Msg
虛擬代理代理
虛擬代理 用於控制對建立開銷很大的本體訪問,它會把本體的實例化推遲到有方法被調用的時候,是最經常使用的一種代理。code
使用虛擬代理來實現圖片預加載cdn
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); }; return { setSrc: function(src) { myImage.setSrc("http://img.lanrentuku.com/img/allimg/1212/5-121204193Q9-50.gif"); img.src = src; } } })(); // 調用方式 ProxyImage.setSrc("https://img.alicdn.com/tps/i4/TB1b_neLXXXXXcoXFXXc8PZ9XXX-130-200.png");
使用虛擬代理實現函數防抖對象
// 函數防抖,頻繁操做中不處理,直到操做完成以後(再過 delay 的時間)才一次性處理,執行最後一次操做 function debounce(fn, delay) { delay = delay || 200; var timer = null; return function() { var arg = arguments; // 每次操做時,清除上次的定時器 clearTimeout(timer); timer = null; // 定義新的定時器,一段時間後進行操做 timer = setTimeout(function() { fn.apply(this, arg); }, delay); } }; var count = 0; // 主體 function scrollHandle(e) { console.log(e.type, ++count); // scroll } // 代理 var proxyScrollHandle = (function() { return debounce(scrollHandle, 500); })(); window.onscroll = proxyScrollHandle;
緩存代理
緩存代理 能夠爲一些開銷大的運算結果提供暫時的緩存,在下一次運算時,若是傳遞進來的參數跟以前一致,則能夠直接返回前面存儲的運算結果。
使用緩存代理計算乘法、加法
// 計算乘法 var mult = function(){ var a = 1; for(var i = 0,ilen = arguments.length; i < ilen; i+=1) { a = a*arguments[i]; } return a; }; // 計算加法 var plus = function(){ var a = 0; for(var i = 0,ilen = arguments.length; i < ilen; i+=1) { a += arguments[i]; } return a; } // 代理函數 var proxyFunc = 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); } }; var proxyMult = proxyFunc(mult); console.log(proxyMult(1,2,3,4)); // 24 console.log(proxyMult(1,2,3,4)); // 緩存取 24 var proxyPlus = proxyFunc(plus); console.log(proxyPlus(1,2,3,4)); // 10 console.log(proxyPlus(1,2,3,4)); // 緩存取 10