首頁 > web前端 > js教程 > 主體

學習JavaScript設計模式之代理模式_javascript技巧

WBOY
發布: 2016-05-16 15:20:24
原創
1068 人瀏覽過
  • 明星都有經紀人作為代理。如果請明星辦一場商演,只能聯絡其經紀人,經紀人會把商演的細節和報酬談好,再把合約交給明星簽。

一、定義

代理模式:提供一個物件一個代用品或占位符,以便控制對它的存取。
代理程式分為:保護代理與虛擬代理
保護代理:用於控制不同權限的對象對目標對象的訪問,在JavaScript中很難判斷誰訪問了某個對象,所以保護代理很難實現。

二、圖片預載(最常見的虛擬代理應用場景)

圖片預先載入是一種常用技術,如果直接給某個img標籤節點設定src屬性,由於圖片過大或網路不佳,圖片的位置往往有段時間會有空白。常見的做法事先用一張loading圖片佔位,然後非同步載入圖片,待圖片載入完成,把其填入img節點裡。
實作原理:
建立一個Image物件:var a = new Image();
定義Image物件的src: a.src = “xxx.gif”;
這樣做就等於是給瀏覽器快取了一張圖片。

可透過Image物件的complete屬性來偵測映像是否已載入完成。每個Image物件都有一個complete屬性,當圖像處於裝載過程中時,該屬性值false,當發生了onload、onerror、onabort中任何一個事件後,則表示圖像裝載過程結束,此時complete屬性為true 。

(1)非代理實作

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)代理實作

// 创建图片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");

登入後複製

使用代理模式的好處:使每個函數功能單一,實現物件設計的「單一職責原則」!

三、檔案同步

假設我們在做一個檔案同步功能,當勾選checkbox時候,它對應的檔案就會被同步到另外一台伺服器。

<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>
登入後複製

沒選中一個checkbox就同步一次,顯然不太合理。因為在web開發中,最大的開銷就是網路請求。
解決方案:透過一個代理函數來收集一段時間之內的請求,然後一次發給伺服器。

var synchronousFile = function(id) {
  console.log("开始同步文件,id为:" + id);
};

var proxySynchonousFile = (function() {
  var cache = [],   // 保存本次需要同步文件的id
    timer;     // 定时器

  return function(id) {
    cache.push(id);
    if(timer) { 
      // 不要覆盖已经启动的定时
      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);
    }
  }
}

登入後複製

四、快取代理–計算乘積(序列一模一樣)

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));
登入後複製

希望本文所述對大家學習javascript程式設計有所幫助。

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板