热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

04代理,迭代器

代理模式为一个对象提供一个代用品或占位符。以便控制对他的访问;面向对象设计原则-单一职责原则就一个类(对象,函数)而言,应该仅有一个引起他变化的原因;(低耦合)代理和本体借口的一致性当不需要代理的时候

代理模式

  • 为一个对象提供一个代用品或占位符。以便控制对他的访问;
面向对象设计原则-单一职责原则
  • 就一个类(对象,函数)而言,应该仅有一个引起他变化的原因;(低耦合)

代理和本体借口的一致性

  • 当不需要代理的时候可以替换回本体

保护代理

  • 过滤请求;可以用于控制不同权限对象对目标对象的访问

虚拟代理

  • 把一些开销很大的对象,延迟到真正需要的时候才创建;
  • 实现图片预加载
var myImage = (function() {
var imgNode = document.createElement('img');
document.body.appendChild(imgNode);
return function(src) {
imgNode.src = src;
};

})();

var proxyImage = (function() {
var img = new Image;
img.Onload= function() {
myImage(this.src);
};
return function(src) {
myImage('picture/loading.jpg');
img.src = src;
}
})();

proxyImage('http://tp3.sinaimg.cn/1805666510/180/5718258464/1');
  • 实现合并请求
var synchrOnousFile= function (id) {
console.log('开始同步 ' + id);
};

var proxySynchrOnousFile= (function() {
var cache = [], timer;
return function(id) {
cache.push(id);
if(timer)
return;
timer = setTimeout(function() {
synchronousFile(cache.join(','));
clearTimeout(timer);
timer = null;
cache.length = 0;
}, 2000); //2秒延迟后一次性处理
};
})();

var checkbox = document.getElementsByTagName('input');
for(var i = 0, c; c = checkbox[i++];) {
c.Onclick= function() {
if(this.checked === true)
proxySynchronousFile(this.id);
}
};

在堕性加载中的应用

var miniCOnsole= (function(){
var cache = [];
var handler = function( ev ){
if ( ev.keyCode === 13 ){ //enter
var script = document.createElement( 'script' );
script.Onload= function(){
for ( var i = 0, fn; fn = cache[ i++ ]; ){
fn();
}
};
script.src = 'log.js';
document.getElementsByTagName( 'head' )[0].appendChild(script);
document.body.removeEventListener( 'keydown', handler );
}
};
document.body.addEventListener( 'keydown', handler, false );
return {
log: function(){
var args = arguments;
cache.push( function(){
return miniConsole.log.apply( miniConsole, args ); //缓存,当真正加载log.js再执行;
});
}
}
})();


miniConsole.log(0);
miniConsole.log(1);
//按下enter

// log.js 代码
miniCOnsole= {
log: function(){
// 真正代码略
console.log( Array.prototype.join.call( arguments ) );
}
};

缓存代理

  • 为一些开销大的运算结果提供暂时的存储
var mult = function () {
var a = 1;
for(var i = 0, len = arguments.length; i a = a * arguments[i];
return a;
};

var proxyMult = (function() {
var cache = {};
return function() {
var args = [].join.call(arguments, ',');
if(args in cache)
return cache[args]
return cache[args] = mult.apply(this, arguments);
};
})();

proxyMult(3,6,8);
  • 用于ajax异步请求: 如分页实现时讲数据缓存,下次请求同一页再输出;

利用高阶函数动态创建代理

  • 如将上面的proxyMult修改,使以后类似计算的缓存代理都用同一个函数产生
var createProxyFactory = function(fn) {
var cache = {};
return function() {
var args = [].join.call(arguments, ',');
if(args in cache)
return cache[args];
return cache[args] = fn.apply(this, arguments);
}
};

var proxyMult = createProxyFactory(mult);

其他代理

  • 防火墙代理:控制网络资源的访问;
  • 远程代理:为一个对象在不同的地址空间提供局部代表;
  • 保护代理:用于对象应该有不同访问权限的情况;
  • 智能引用代理:取代简单的指针,在访问对象时执行一些附加操作;
  • 写时即复制代理:通常用于复制一个庞大对象的情况;他延迟了复制的过程,当对象真正被修改时才进行复制;

  • 在编写业务代码的时候往往不需要预先设置使用代理模式,当真正发现不方便直接访问某个对象的时候再使用;

迭代器模式

  • 顺序访问一个聚合对象中各个元素,而又不需要暴露该对象的内部表示的方法;
  • 现在流行的大部分语言都有内置的迭代器实现;JS中如Array.prototype.forEach

内部迭代器

  • 内部已经定义好了迭代规则
var each = function (arr, callback) {
for(var i = 0, len = arr.length; i callback.call(arr, i, arr[i]); //这里可以修改对象
};

each([1,2,3], function(index, value) {
console.log(this,index,value);
});

外部迭代器

  • 必须显示地请求迭代下一个元素;增加了复杂度,但也增强累迭代器的灵活性;可以手工控制迭代过程;
var Iterator = function(obj) {
var current = 0, len = obj.length;
var next = function() {
current++;
}
var isDOne= function() {
return current >= len; //如果length会自动修改那直接使用
}
var getCurrentIten = function() {
return obj[current];
}
return {
next: next,
isDone: isDone,
getCurrentIten: getCurrentIten
}
};
//一个比较数组相等的例子
var compare = function(iterator1, iterator2) {
while(!iterator1.isDone() || !iterator2.isDone()) {
if(iterator1.getCurrentIten() !== iterator2.getCurrentIten())
throw new Error('不相等');
iterator1.next();
iterator2.next();
}
console.log('相等');
};

compare(Iterator([0,1,2]), Iterator([0,1,2]));

另一个迭代器实现

var Iterator = function (items, container) {
var cOntainer= container && document.getElementById(container) || document.body,
items = container.getElementsByTagName(items),
len = items.length,
index = 0,
splice = [].splice;
return {
first: function () {
index = 0;
return items[index];
},
second: function () {
index = len - 1;
return items[index];
},
pre: function () {
if(--index > 0)
return items[index];
else {
index = 0;
return null;
}
},
next: function () {
if(++index return items[index]
else {
index = len - 1;
return null;
}
},
get: function (num) {
index = num >= 0 ? num % len : num % len + len;
return items[index];
},
dealEach: function (fn) {
var args = splice.call(arguments, 1);
for(var i = 0; i fn.apply(items[i], args);
}
},
dealItem: function (num, fn) {
fn.apply(this.get(num), splice.call(arguments, 2))
},
exclusive: function (num, allFn, numFn) {
this.dealEach(allFn);
if(Object.prototype.toString.call(num) === '[object Array]') {
for(var i = 0, l = num.length; i this.dealItem(num[i], numFn);
}
} else {
this.dealItem(num, numFn);
}
}
}
};

var demo = new Iterator('li', 'container');
console.log(demo.first());
console.log(demo.pre());
console.log(demo.next());
console.log(demo.get(3));
demo.dealEach(function(text, color) {
this.innerHTML = text;
this.style.background = color;
}, 'test', 'pink');

demo.exclusive([2,3], function () {
this.innerHTML = '被排除的';
this.style.background = 'green';
}, function () {
this.innerHTML = '被选中的';
this.style.background = 'red';
})

迭代类数组和字面量对象

  • 实际上只要聚合对象拥有length属性并可以下标访问就可以被迭代

应用例子

  • 比如一个功能里使用try-catch,if-else等根据实际情况尝试不同的执行函数;
  • 可以将所有要尝试的函数单独分开并设置尝试执行失败返回false;
  • 将所有要尝试的函数通过高迭代器执行,以后增加新的执行函数,只要按照一定顺序迭代就可以;
var iterator = function() {
for(var i = 0, fn; fn = arguments[i++];) {
var result = fn();
if(result !== false)
return result;
}
};

iterator(fn1, fn2, fn3, fn4);

同步变量迭代器

//同步变量
var A = {
common: {},
client: {
user: {
username: '',
uid: ''
}
},
server: {}
};

//同步变量迭代取值器
var AGetter = function (key) {
if(!A) return;
var result = A;
key = key.split('.');
for(var i = 0, l = key.length; i if(result[key[i]] !== undefined) {
result = result[key[i]];
} else {
return;
}
}
return result;
};

//同步变量迭代赋值器
var ASetter = function (key, val) {
if(!A) return;
var result = A;
key = key.split('.');
for(var i = 0, l = key.length; i if (result[key[i]] === undefined) {
result[key[i]] = {};
}
if (!(result[key[i]] instanceof Object)) {
throw new Error('A. ' + key.splice(0, i + 1).join('.') + ' is not Object');
return false;
}
result = result[key[i]];
}
return result[key[i]] = val;
};

console.log(AGetter('client.user.username'));
console.log(ASetter('client.server.new', 'on'));

推荐阅读
  • 优化升级版数据采集与赋值方法,专为前文内容设计
    在前一篇文章中,方法的局限性主要体现在需要传递参数,并且参数数量受限。当页面布局与所需参数不匹配时,该方法将无法正常工作。为此,我们推出了优化升级版1.1,旨在解决这些问题并提高灵活性和适用性。 ... [详细]
  • OBS Studio自动化实践:利用脚本批量生成录制场景
    本文探讨了如何利用OBS Studio进行高效录屏,并通过脚本实现场景的自动生成。适合对自动化办公感兴趣的读者。 ... [详细]
  • 解决JavaScript中法语字符排序问题
    在开发一个使用JavaScript、HTML和CSS的Web应用时,遇到从SQLite数据库中提取的法语词汇排序不正确的问题,特别是带重音符号的字母未按预期排序。 ... [详细]
  • 理解浏览器历史记录(2)hashchange、pushState
    阅读目录1.hashchange2.pushState本文也是一篇基础文章。继上文之后,本打算去研究pushState,偶然在一些信息中发现了锚点变 ... [详细]
  • 高效的JavaScript异步资源加载解决方案
    本文探讨了如何通过异步加载技术处理网页中大型第三方插件的加载问题,避免将大文件打包进主JS文件中导致的加载时间过长,介绍了实现异步加载的具体方法及其优化。 ... [详细]
  • 基于 Vue 和 Element UI 实现的简洁登录界面设计
    本文介绍了一种利用 Vue.js 和 Element UI 框架构建的简洁登录界面设计。该设计不仅注重用户体验,还确保了界面的美观性和易用性。通过合理的布局和组件配置,实现了高效、响应式的登录功能,适用于多种前端应用场景。 ... [详细]
  • ButterKnife 是一款用于 Android 开发的注解库,主要用于简化视图和事件绑定。本文详细介绍了 ButterKnife 的基础用法,包括如何通过注解实现字段和方法的绑定,以及在实际项目中的应用示例。此外,文章还提到了截至 2016 年 4 月 29 日,ButterKnife 的最新版本为 8.0.1,为开发者提供了最新的功能和性能优化。 ... [详细]
  • 本文详细介绍了 jQuery 的入门知识与实战应用,首先讲解了如何引入 jQuery 库及入口函数的使用方法,为初学者提供了清晰的操作指南。此外,还深入探讨了 jQuery 在实际项目中的多种应用场景,包括 DOM 操作、事件处理和 AJAX 请求等,帮助读者全面掌握 jQuery 的核心功能与技巧。 ... [详细]
  • 2017-09-07前端日报精选JavaScriptEventLoop机制详解与Vue.js中实践应用Redux基础与实践如何用js获取虚拟键盘高度?( ... [详细]
  • 使用vue.js实现checkbox的全选,和多个的删除欢迎大家来我的博客浏览更多的干货内容www.jaxqin.comtemplate代码:<template> ... [详细]
  • 微信html替换右键菜单,jquery右键菜单
    插件描述:一个最简单的,很好看的jQuery右键菜单一个最简单的,很好看的jQuery右键菜单特点唯一的依赖是jQuery。简单的API。 ... [详细]
  • Level:  Medium题目描述:Givenanon-emptystringsandadictionarywordDictcontainingalistofnon-emptyw ... [详细]
  • 使用jqTransform插件美化表单
    jqTransform 是由 DFC Engineering 开发的一款 jQuery 插件,专用于美化表单元素,操作简便,能够美化包括输入框、单选按钮、多行文本域、下拉选择框和复选框在内的所有表单元素。 ... [详细]
  • Android ListView 自定义 CheckBox 实现列表项多选功能详解
    本文详细介绍了在Android开发中如何在ListView的每一行添加CheckBox,以实现列表项的多选功能。用户不仅可以通过点击复选框来选择项目,还可以通过点击列表的任意一行来完成选中操作,提升了用户体验和操作便捷性。同时,文章还探讨了相关的事件处理机制和布局优化技巧,帮助开发者更好地实现这一功能。 ... [详细]
  • UI组件:ext、JqueryEasyUI、miniui、dhtmlx及自定义页面
    这篇博文主要是分析下当前经常使用到的UI组件,他们的效果和功能一般都可以满足我们平常项目使用,但对于较复杂些的项目建议你要斟酌下再决定是否使用ÿ ... [详细]
author-avatar
踏山321
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有