学习JavaScript设计模式之代理模式


Posted in Javascript onJanuary 12, 2016
  • 明星都有经纪人作为代理。如果请明星办一场商演,只能联系其经纪人,经纪人会把商演的细节和报酬谈好,再把合同交给明星签。

一、定义

代理模式:为一个对象提供一个代用品或占位符,以便控制对它的访问。
代理分为:保护代理和虚拟代理
保护代理:用于控制不同权限的对象对目标对象的访问,在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程序设计有所帮助。

Javascript 相关文章推荐
javascript 延迟加载技术(lazyload)简单实现
Jan 17 Javascript
datagrid框架的删除添加与修改
Apr 08 Javascript
Jquery实现页面加载时弹出对话框代码
Apr 19 Javascript
通过pjax实现无刷新翻页(兼容新版jquery)
Jan 31 Javascript
将数字转换成大写的人民币表达式的js函数
Sep 21 Javascript
JS实现的适合做faq或menu滑动效果示例
Nov 17 Javascript
JS中对数组元素进行增删改移的方法总结
Dec 15 Javascript
原生JS实现《别踩白块》游戏(兼容IE)
Feb 20 Javascript
微信小程序开发之从相册获取图片 使用相机拍照 本地图片上传
Apr 18 Javascript
js轮播图透明度切换(带上下页和底部圆点切换)
Apr 27 Javascript
js实现点击切换checkbox背景图片的简单实例
May 08 Javascript
node文件上传功能简易实现代码
Jun 16 Javascript
基于JavaScript实现TAB标签效果
Jan 12 #Javascript
JavaScript实现瀑布流布局
Jun 28 #Javascript
轻松实现JavaScript图片切换
Jan 12 #Javascript
jQuery动画效果图片轮播特效
Jan 12 #Javascript
jQuery动画效果实现图片无缝连续滚动
Jan 12 #Javascript
jqueryMobile使用示例分享
Jan 12 #Javascript
WordPress中鼠标悬停显示和隐藏评论及引用按钮的实现
Jan 12 #Javascript
You might like
在DC的漫画和电影中,蝙蝠侠的宿敌,小丑的真名是什么?
2020/04/09 欧美动漫
一个php作的文本留言本的例子(一)
2006/10/09 PHP
php下MYSQL limit的优化
2008/01/10 PHP
dedecms函数分享之获取某一栏目所有子栏目
2014/05/19 PHP
destoon调用discuz论坛中带图片帖子的实现方法
2014/08/21 PHP
PHP中的替代语法简介
2014/08/22 PHP
PHP常用的排序和查找算法
2015/08/06 PHP
Laravel Memcached缓存驱动的配置与应用方法分析
2016/10/08 PHP
PHP实现数组转JSon和JSon转数组的方法示例
2018/06/14 PHP
PHP实现常用排序算法的方法
2020/02/05 PHP
修改jquery里的dialog对话框插件为框架页(iframe) 的方法
2010/09/14 Javascript
防止浏览器记住用户名及密码的简单实用方法
2013/04/22 Javascript
jq实现酷炫的鼠标经过图片翻滚效果
2014/03/12 Javascript
jquery实现隐藏在左侧的弹性弹出菜单效果
2015/09/18 Javascript
Jquery对新插入的节点 绑定Click事件失效的解决方法
2016/06/02 Javascript
Vue开发Html5微信公众号的步骤
2019/04/11 Javascript
vue 集成jTopo 处理方法
2019/08/07 Javascript
浅析Python中的多重继承
2015/04/28 Python
python中尾递归用法实例详解
2015/04/28 Python
Python开发的实用计算器完整实例
2017/05/10 Python
VScode编写第一个Python程序HelloWorld步骤
2018/04/06 Python
python解决pandas处理缺失值为空字符串的问题
2018/04/08 Python
python3+PyQt5泛型委托详解
2018/04/24 Python
Python运维自动化之nginx配置文件对比操作示例
2018/08/29 Python
Python搭建Spark分布式集群环境
2019/07/05 Python
Python+Redis实现布隆过滤器
2019/12/08 Python
python实现五子棋游戏(pygame版)
2020/01/19 Python
基于html5实现的图片墙效果
2014/10/16 HTML / CSS
高街生活方式全球在线商店:AZBRO
2017/08/26 全球购物
Speedo速比涛中国官方网站:全球领先泳装运动品牌
2018/04/24 全球购物
康帕斯酒店预订:Compass Hospitality(支持中文)
2018/08/23 全球购物
奥地利手表、香水、化妆品和珠宝购物网站:Brasty.at
2021/01/17 全球购物
井冈山红色之旅感想
2014/10/07 职场文书
巾帼建功标兵先进事迹材料
2016/02/29 职场文书
vue3中的组件间通信
2021/03/31 Vue.js
Pyhton模块和包相关知识总结
2021/05/12 Python