设计模式知识连载(35)---迭代器模式:

<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>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值