闭包应用之高阶编程函数

  1. 惰性函数
    特点:懒、能执行一次的绝对不会执行第二次
    <script>
        //如此编写,每一次执行方法都需要处理兼容:其实这种操作是没有必要的,第一次执行已经知道兼容情况了,后期在执行方法(浏览器也没有刷新,也没有换浏览器)兼容校验是没必要处理的
        function getCss(element,attr){
            if(window.getComputedStyle){
                return window.getComputedStyle(element)[attr];
            }
            //IE6~8
            return element.currentStyle[attr];
        }

        //改进:页面一加载就把是否兼容处理了,后期执行方法直接基于变量的值判断使用哪个方法即可
        let isCompatible='getComputedStyle' in window;
        function getCss(element,attr){
            if(isCompatible){
                return window.getComputedStyle(element)[attr];
            }
            //IE6~8
            return element.currentStyle[attr];
        }

        //惰性函数来解决:函数重构
        //getCss是全局函数
        //第一次执行会产生闭包
        function getCss(element,attr){
            // EC(1)闭包
            //   element:body
            //   attr:width
            //   作用域链:<EC(1),EC(G)>
            if(window.getComputedStyle){
                //把全局的getCss重构成为具体的小函数
                getCss=function (element,attr){
                    return window.getComputedStyle(element)[attr];
                };
            }else{
                getCss=function (element,attr){
                    return element.currentStyle[attr];
                }
            }
            //重构后首先执行一次,确保第一次调用getCss也可以获取到自己想要的结果
            return getCss(element,attr);
        }
        console.log(getCss(document.body,'width'));
        //第二次执行:执行的是重构后的小函数,这样告别了兼容校验的操作
        console.log(getCss(document.body,'padding'));
        console.log(getCss(document.body,'margin'));
    </script>
  1. 柯里化函数
    预处理思想、应用的也是闭包的机制
    (1)ES6中的剩余运算符:…args,把传递进来的实参获取到(排除基于其他形参获取的信息)
    <script>
        function fn(...args){
            console.log(args);  //数组集合
            console.log(arguments); //类数组集合
        }
        fn(1,2);
    </script>

(2)柯里化函数:第一次执行大函数,形成一个闭包(原因:返回一个小函数),把一些信息存储到闭包中(传递的实参信息或当前闭包中声明的一些私有变量等信息);等到后来需要把返回的小函数anonymous执行,遇到一些非自己私有变量,则向其上级上下文中查找(也就是把之前存储在闭包中的信息获取到):如下的代码

    <script>
        function fn(...outerArgs){
            //outerArgs存放第一次执行fn传递的实参信息[1,2]
            return function anonymous(...innerArgs){
                //innerArgs存放第二次执行匿名函数传递执行实参信息[3]
                let arr=outerArgs.concat(innerArgs);
                return arr.reduce(function (total,item){
                    return total+item;
                })
            }
        }
        let res=fn(1,2)(3);
        console.log(res); //返回结果是1+2+3=6
    </script>
  1. reduce:数组中用来迭代遍历每一项的
    (1)
    <script>
        // arr.reduce(function([result],[item]){
          // [result]
             // 和callback的同级级别中
             //如果传递了[value]值,则第一次执行callback,里面的[result]存储的是参数信息;
             //同时item迭代的是数组中的第一项
        // }[,value])
        let arr=[10,20,30,40];
        arr.reduce(function(result,item){
            console.log(result,item);  //result=0  item=10(数组中的第一项)
        },0);
        
        arr.reduce(function(result,item){
            console.log(result,item);   //result=10  item=20 分别是数组中的第一项和第二项
        })
    </script>

(2)

    <script>
        let arr=[10,20,30,40];
        let n=arr.reduce(function(total,item){
        //把当前callback执行返回的结果,做为下一次迭代中的[result]处理
            return total+item;
        },0);
        console.log(n);
    </script>
  1. 自己实现reduce
    <script>
        function reduce(arr,callback,init){
            arr=arr.slice(0);
            if(init===undefined){
                init=arr[0];
                arr=arr.slice(1);
            }
            for(let i=0;i<arr.length;i++){
                let item=arr[i];
                index=i;
                init=callback(init,item,index);
            }
            return init;
        }
        let arr=[10,20,30,40];
        let result=reduce(arr,function (result,item,index){
            return result+item;
        });
        console.log(result);

       result=reduce(arr,function (result,item,index){
            return result+item;
        },100);
        console.log(result);
    </script>

在传值的时候index是从0开始的,在没有传值的时候index是从1开始的,reduce函数的改进(最全的情况),如下所示:

        function reduce(arr,callback,init){
            arr=arr.slice(0);
            let result=init;
            for(let i=0;i<arr.length;i++){
                if(init===undefined && i===0){
                    // init没有传递值(只有第一轮特殊)
                    result=arr[0];
                    let item=arr[1],
                        index=1;
                    //只有一项的时候,index没有值,所以直接返回结果
                    if(!item) return result;
                    result=callback(result,item,index);
                    i++;
                    // break;
                    continue;
                }
                //init传递值了
                let item=arr[i],
                    index=i;
                result=callback(result,item,index);

            }
            return result;
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值