设计模式知识连载(43)---参与者模式:

<body>


<h3>设计模式知识连载(43)---参与者模式:</h3>
<p>
    在特定的作用域中执行给定的函数,并将参数原封不动的传递。
</p>

<hr>

<button>点击</button>
<p>hello</p>



<script type="text/javascript">


    /**
    *   案例一:传递数据,方式一:初始
    */
    // // 单体模式定义命名空间
    // var A = {} ;
    // // 事件绑定方法
    // A.event.on = function(dom, type, fn) {
    //  // w3c标准事件绑定
    //  if(dom.addEventListener) {
    //      dom.addEventListener(type, fn, false) ;
    //  // IE事件绑定
    //  }else if(dom.attachEvent) {
    //      dom.attachEvent('on' + type, fn) ;
    //  // DOM0级事件绑定
    //  }else {
    //      dom['on' + type] = fn ;
    //  }
    // }

    /**
    *   案例一:传递数据,方式二:进阶
    */
    // // 单体模式定义命名空间
    // var A = {} ;
    // // 事件绑定方法
    // A.event.on = function(dom, type, fn, data) {
    //  // w3c标准事件绑定
    //  if(dom.addEventListener) {
    //      dom.addEventListener(type, function(e) {
    //          *
    //          *   在dom环境中调用fn,并传入事件对象与data数据参数
    //          *   
    //          *   知识点:JavaScript中的call和apply方法可以使我们在特定作用域中执行某个函数,并传入参数。所以,在该回调函数中,我们这可以借助call函数实现。

    //          fn.call(dom, e, data) ;
    //      }, false) ;
    //  }else if(dom.attachEvent) {
    //      dom.attachEvent('on' + type, function(e) {
    //          fn.call(dom, e, data) ;
    //      }) ;
    //  }else {
    //      dom['on' + type] = function(e) {
    //          fn.call(dom, e, data) ;
    //      }
    //  }
    // }


    /**
    *   案例二:函数绑定,方式一:
    */
    // // 函数绑定bind
    // function bind(fn, context) {
    //  // 闭包返回新函数
    //  return function() {
    //      // 对fn装饰并返回
    //      return fn.apply(context, arguments) ;
    //  }
    // }

    // // 测试用例:
    // var demoObj = {
    //  title : '这是一个例子'
    // } ;
    // function demoFn() {
    //  console.log(this.title) ;
    // } ;
    // // 让demoObj参与demoFn的执行 
    // var bindFn = bind(demoFn, demoObj) ;
    // demoFn() ;   // undefined
    // bindFn() ;   // 这是一个例子


    /**
    *   案例二:函数绑定,方式二:
    */
    // // 函数绑定bind
    // function bind(fn, context) {
    //  // 闭包返回新函数
    //  return function() {
    //      // 对fn装饰并返回
    //      return fn.apply(context, arguments) ;
    //  }
    // }
    // var btn = document.getElementsByTagName('button')[0] ;
    // var p = document.getElementsByTagName('p')[1] ;
    // // 对demoFn改进,在控制台输出参数与this对象
    // function demoFn() {
    //  console.log(arguments) ;
    //  console.log('-----------------------') ;
    //  console.log(this) ;
    // }

    // // 未设置提供参与对象
    // var bindFn = bind(demoFn) ;
    // // 绑定事件
    // btn.addEventListener('click', bindFn) ;

    // var bindFn = bind(demoFn, btn) ;
    // // 提供btn元素参与对象
    // btn.addEventListener('click', bindFn) ;

    // var bindFn = bind(demoFn, p) ;
    // // 提供p元素参与对象
    // btn.addEventListener('click', bindFn) ;

    // // 移除事件【移除最近的那个】
    // btn.removeEventListener('click', bindFn) ;



    /**
    *   案例三:函数柯里化,方式一:
    */
    // 函数柯里化
    function curry(fn) {
        // 缓存数组slice方法Array.prototype.slice
        var _slice = [].slice ;
        // 从第二个参数开始截取参数
        var args = _slice.call(arguments, 1) ;
        // 闭包返回新函数
        return function() {
            // 将参数(类数组)转化为数组
            var addArgs = _slice.call(arguments) ;
            // 拼接参数
            var allArgs = args.concat(addArgs) ;
            // 返回新函数
            return fn.apply(null, allArgs) ;
        }
    }

    // 测试用例
    // 正常加法器
    function add(num1, num2) {
        return num1 + num2 ;
    }
    // 加5加法器
    function add5(num) {
        return add(5, num) ;
    }
    // 测试加法器
    console.log('1 + 2 = ', add(1, 2)) ;
    // 测试加5加法器
    console.log('5 + 6 = ', add5(6)) ;
    // 函数柯里化创建加5加法器
    var curry_add5 = curry(add, 5) ;
    console.log('5 + 7 = ', curry_add5(7)) ;
    var curry_add7_8 = curry(add, 7, 8) ;
    console.log('7 + 8 = ', curry_add7_8()) ;


    /**
    *   案例三:反柯里化,方式一:
    */
    // 反柯里化
    Function.prototype.uncurry = function() {
        // 保存当前对象
        var that = this;
        return function() {
            return Function.prototype.call.apply(that, arguments) ;
        }
    }
    // 测试用例
    // 用Object.prototype.toString校验对象类型时:
    // 获得校验方法
    var toString = Object.prototype.toString.uncurry() ;
    // 测试对象数据类型
    console.log('toString(function(){}):', toString(function(){})) ;
    console.log('toString([]):', toString([])) ;
    // 用数组的push方法为对象添加数据成员:
    // 保存数组push方法
    var push = [].push.uncurry() ;
    // 创建一个对象
    var demoArr = {} ;
    // 通过push方法为对象添加数据成员
    push(demoArr, '第一个成员', '第二个成员') ;
    console.log(demoArr) ;

    /**
    *   案例四:重构bind,方式一:
    */
    // 重写bind
    function bind(fn, context) {
        // 缓存数组的slice方法
        var _slice = Array.prototype.slice;
        // 从第三个参数开始截取参数(包含第三个参数)
        var args = _slice.call(arguments, 2) ;
        // 返回新方法
        return function() {
            // 将参数转化为数组
            var addArgs = _slice.call(arguments) ;
            // 拼接参数
            var allArgs = addArgs.concat(args) ;
            // 对fn装饰并返回
            return fn.apply(context, allArgs) ;
        }
    }
    // 测试用例
    var btn = document.getElementsByTagName('button')[0] ;
    var p = document.getElementsByTagName('p')[1] ;
    var demoData1 = {
        text : '这是第一组数据'
    };
    var demoData2 = {
        text : '这是第二组数据'
    }
    function demoFn() {
        console.log('arguments:', arguments) ;
        console.log('----------------------') ;
        console.log('this:', this) ;
    }
    // 提供btn元素、demoData1参与对象
    // var btnFn = bind(demoFn, btn, demoData1) ;
    // btn.addEventListener('click', btnFn) ;

    // 提供btn元素、demoData1、demoData2参与对象
    // var btnFn2 = bind(demoFn, btn, demoData1, demoData2) ;
    // btn.addEventListener('click', btnFn2) ;

    // 提供p元素、demoData1参与对象
    // var btnFn3 = bind(demoFn, p, demoData1) ;
    // btn.addEventListener('click', btnFn3) ;

    /* 看看浏览器内置的bind方法 */
    var bindFn_browser = bind(p, demoData1) ;
    btn.addEventListener('click', bindFn_browser) ;



    /**
    *   案例五:兼容各个浏览器,方式一:
    */
    // 兼容各个浏览器
    if(Function.prototype.bind === undefined) {
        Function.prototype.bind = function(context) {
            // 缓存数组slice方法
            var _slice = Array.prototype.slice;
            // 从第二个参数截取参数
            var args = _slice.call(arguments, 1) ;
            // 保存当前函数引用
            var that = this ;
            // 返回新的函数
            return function() {
                // 将参数数组化
                var addArgs = _slice.call(arguments) ;
                // 拼接参数,注意:传入的参数放在了后面
                var allArgs = args.concat(addArgs) ;
                // 对当前函数装饰并返回
                return that.apply(context, allArgs) ;
            }
        }
    }
</script>   

</body>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值