<body>
<h3>设计模式知识连载(35)---迭代器模式:</h3>
<p>
在不暴露对象内部结构的同时,可以顺序地访问聚合对象内部的元素
</p>
<hr>
<div id = 'container'>
<ul>
<li>111111111</li>
<li>222222222</li>
<li>333333333</li>
<li>444444444</li>
<li>555555555</li>
</ul>
</div>
<hr>
<div>
<p><image src = 'icon/1.png'></image></p>
<hr>
<p><canvas></canvas></p>
</div>
<script type="text/javascript">
/**
* 案例一:焦点图,方式一:初始
*/
// 迭代器
var Iterator = function(items, container) {
// 获取父容器,若container参数存在,并且可以获取该元素则获取,否则获取document
var _container = container && document.getElementById(container) || document ;
// 获取元素
var _items = _container.getElementsByTagName(items) ;
// 获取元素长度
var _len = _items.length ;
// 当前索引值,默认:0
var _index = 0 ;
// 缓存原生数组splice方法
var _splice = [].splice ;
return {
// 获取第一个元素
first : function() {
// 校正当前索引
_index = 0 ;
// 获取第一个元素
return _items[_index] ;
} ,
// 获取最后一个元素
last : function() {
// 校正当前索引
_index = _len - 1 ;
return _items[_index] ;
},
// 获取前一个元素
pre : function() {
// 如果索引值大于0
if(--_index > 0) {
// 获取索引值对应的元素
return _items[_index] ;
}else{
// 索引值为0
_index = 0 ;
// 返回空
return null ;
}
} ,
// 获取后一个元素
next : function() {
// 如果索引值小于长度
if(++_index < _len) {
// 获取索引值对应的元素
return _items[_index] ;
}else {
// 索引值为_len - 1
_index = _len - 1 ;
// 返回空
return null ;
}
},
// 获取某一个元素
get : function(num) {
// 如果num大于等于0再获取正向获取,否则逆向获取
_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 < _len; i ++) {
// 对元素执行回调函数
fn.apply(_items[i], _args) ;
}
},
// 对某一个元素执行某一个方法
dealItem : function(num, fn) {
// 对元素执行回调函数,
// 注:1、第三个参数开始为回调函数中参数
// 2、通过this.get方法设置index索引值
fn.apply(this.get(num), _splice.call(arguments, 2)) ;
},
// 排它方式处理某一个元素
exclusive : function(num, allFn, numFn) {
// 对所有元素执行回调函数
this.dealEach(allFn) ;
// 如果num类型为数组
if(Object.prototype.toString.call(num) === '[object Array]') {
// 遍历num数组
for(var i = 0; i < num.length; i++) {
this.dealItem(num[i], numFn) ;
}
}else {
// 处理第num个元素
this.dealItem(num, numFn) ;
}
}
}
}
// 测试用例:
var demo = new Iterator('li', 'container') ;
console.log('demo.first():', demo.first()) ;
console.log('demo.pre():', demo.pre()) ;
console.log('demo.next():', demo.next()) ;
console.log('demo.pre():', demo.pre()) ;
console.log('demo.last():', demo.last()) ;
console.log('demo.pre():', demo.pre()) ;
console.log('demo.next():', demo.next()) ;
console.log('demo.get(2000):', demo.get(2000)) ;
console.log('demo.get(3):', demo.get(3)) ;
// 处理所有元素
// demo.dealEach(function(text, color) {
// // 设置内容
// this.innerHTML = text ;
// // 设置背景色
// this.style.background = color ;
// }, 'test', 'pink') ;
// 排它思想处理第3个和第4个
demo.exclusive([2, 3], function() {
this.innerHTML = '被排除的' ;
this.style.background = 'red' ;
}, function() {
this.innerHTML = '选中的' ;
this.style.background = 'green' ;
}) ;
/**
* 案例二:数组迭代器,方式一:初始
*
* 作用:解决低版本的IE浏览器兼容问题
*/
var eachArray = function(arr, fn) {
var i = 0 ;
var len = arr.length ;
// 遍历数组
for(; i < len; i++) {
// 依次执行回调函数,注意回调函数中传入的参数第一个为索引,第二个为该索引对应的值
if(fn.call(arr[i], i, arr[i]) === false) {
break ;
}
}
}
// 测试用例:
// for(var arr = [], i = 0; i < 5; arr[i++] = i);
var arr = [] ;
var i = 0 ;
for(; i < 5; i++) {
arr.push(i + 1) ;
}
eachArray(arr, function(i, data) {
console.log(i, data) ;
}) ;
/**
* 案例三:对象迭代器,方式一:初始
*/
var eachObject = function(obj, fn) {
// 遍历对象中的每一个属性
for(var i in obj) {
// 一次执行回调函数,注意回调函数中传入的参数第一个为属性,第二个为该属性对应的值
if(fn.call(obj[i], i, obj[i]) === false) {
break ;
}
}
}
// 测试用例:
var obj = {
a : 111,
b : 222,
c : 333
}
eachObject(obj, function(i, data) {
console.log(i, data) ;
}) ;
/**
* 案例四:同步变量迭代器,方式一:初始
*/
var G = {
p : {
s : 'GPS'
}
} ;
// var s = G.p.s ; // 代码不严谨
var s = G && G.p && G.p.s ; // 这样写才严谨
console.log(s) ;
/**
* 案例四:同步变量迭代器,方式二:进阶
*/
// 同步变量
var A = {
// 所有用户公有
common : {},
// 客户端数据
client : {
user : {
uid : '0123-4567-8910',
username : '雨打芭蕉'
}
},
// 服务端数据
server : {}
} ;
// 同步变量迭代取值器
var AGetter = function(key) {
// 如果不存在A,则返回为定义
if(!A) {
return undefined ;
}
// 获取同步变量A对象
var _result = A ;
// 解析属性层次序列
var _key = key.split('.') ;
// 迭代同步变量A对象属性
for(var i = 0; i < _key.length; i++) {
// 如果第i层属性存在对应的值则迭代该属性值
if(_result[_key[i]] !== undefined) {
_result = _result[_key[i]] ;
// 如果不存在则返回未定义
}else {
return undefined ;
}
}
// 返回获取的结果
return _result ;
}
// 测试用例:
// 获取用户名数据
console.log(AGetter('client.user.username')) ;
// 获取本地语言数据
console.log(AGetter('server.lang.local')) ;
// 同步变量迭代取值器
var ASetter = function(key, val) {
// 如果不存在A则返回未定义
if(!A) {
return false ;
}
// 获取同步变量A对象
var _result = A ;
// 解析属性层次序列
var _key = key.split('.') ;
// 设置循环变量
var i = 0 ;
// 获取数组长度
var _len = _key.length ;
// 迭代同步变量A对象属性
for(; i < _len - 1; i++) {
// 如果第i层属性对应的值不存在,则定义为对象
if(_result[_key[i]] === undefined) {
_result[_key[i]] = {} ;
}
// 如果i层属性对应的值不是对象(Object)的一个实例,则抛出错误
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(ASetter('client.module.news.sports', 'on')) ;
console.log(AGetter('client.module.news.sports'));
// 为值类型数据添加属性是不允许的
// console.log(ASetter('client.user.username.sports', 'on')) ;
// object.html:298 Uncaught Error: A.client.user.username is not Object
/**
* 案例五【不能运行】:分支循环嵌套问题,方式一:初始
*/
// window.onload = function() {
// // 获取画布
// var canvas = document.getElementsByTagName('canvas')[0] ;
// // 获取图片
// var img = document.images[0] ;
// // 获取并设置宽度
// var width = (canvas.width = img.width * 2) / 2 ;
// // 获取并设置高度
// var height = canvas.height = img.height ;
// // 获取渲染上下文
// var ctx = canvas.getContext('2d') ;
// // 绘制图片
// ctx.drawImage(img, 0, 0) ;
// /***
// * 绘制特效图片
// * param t 特效类型
// * param x x坐标
// * param y y坐标
// * param w 宽度
// * param h 高度
// * param a 透明度
// ****/
// function dealImage(t, x, y, w, h, a) {
// // 获取画布图片数据
// var canvasData = ctx.getImageData(x, y, w, h) ;
// // 获取像素数据
// var data = canvasData.data ;
// // 遍历每组像素数据(4个数据表示一个像素点数据,分别代表红色、绿色、蓝色、透明度)
// for(var i = 0; i < data.length; i +=4) {
// switch(t) {
// // 红色滤镜,将绿色与蓝色取值为0
// case 'red' :
// data[i + 1] = 0 ;
// data[i + 2] = 0 ;
// data[i + 3] = a ; break ;
// // 绿色滤镜,将红色和蓝色取值为0
// case 'green' :
// data[i] = 0 ;
// data[i + 2] = 0 ;
// data[i + 3] = a ;
// break ;
// // 蓝色滤镜,将红色和绿色取值为0
// case 'blue' :
// data[i] = 0 ;
// data[i + 1] = 0 ;
// data[i + 3] = a ;
// break ;
// // 平均值灰色滤镜,去三色平均值
// case 'gray' :
// var num = parseInt(data[i] + data[i + 1] + data[i + 2] / 3) ;
// data[i] = num ;
// data[i + 1] = num ;
// data[i + 2] = num ;
// data[i + 3] = a ;
// break ;
// // 其他方案
// };
// }
// // 绘制处理后的图片
// ctx.putImageData(canvasData, width + x, y) ;
// } ;
// // // 为图片添加特效
// dealImage('gray', 0, 0, width, height, 255) ;
// // dealImage('gray', 100, 50, 300, 200, 100) ;
// // dealImage('gray', 150, 100, 200, 100, 255) ;
// }
/**
* 案例五【不能运行】:分支循环嵌套问题,方式二:进阶
*/
// window.onload = function() {
// // 获取画布
// var canvas = document.getElementsByTagName('canvas')[0] ;
// // 获取图片
// var img = document.images[0] ;
// // 获取并设置宽度
// var width = (canvas.width = img.width * 2) / 2 ;
// // 获取并设置高度
// var height = canvas.height = img.height ;
// // 获取渲染上下文
// var ctx = canvas.getContext('2d') ;
// // 绘制图片
// ctx.drawImage(img, 0, 0) ;
// /***
// * 绘制特效图片
// * param t 特效类型
// * param x x坐标
// * param y y坐标
// * param w 宽度
// * param h 高度
// * param a 透明度
// ****/
// function dealImage(t, x, y, w, h, a) {
// var canvasData = ctx.getImageData(x, y, w, h) ;
// var data = canvasData.data ;
// // 状态模式封装算法
// var Deal = (function() {
// var method = {
// // 默认类型——平均灰度特效
// 'default' : function(i) {
// return method['gray'](i) ;
// },
// // 红色特效
// 'red' : function(i) {
// data[i + 1] = 0 ;
// data[i + 2] = 0 ;
// data[i + 3] = a ;
// },
// // 平均灰度特效
// 'gray' : function(i) {
// // 将红、绿、蓝色取平均值
// data[i] = data[i + 1] = parseInt(data[i + 2] = (data[i] + data[i + 1] + data[i + 2]) / 3) ;
// data[i + 3] = a ;
// }
// };
// // 主函数,通过给定类型返回对应过滤镜算法
// return function(type) {
// return method[type] || method['default'] ;
// }
// })()
// } ;
// // 迭代器处理数据
// function eachData(fn) {
// for(var i = 0, len = data.length; i < len; i +=4) {
// // 处理一组像素数据
// fn(i) ;
// }
// }
// // 处理数据
// eachData(Deal(t)) ;
// ctx.putImageData(canvasData, width + x, y) ;
// }
</script>
</body>
设计模式知识连载(35)---迭代器模式:
最新推荐文章于 2022-06-07 14:35:17 发布