JavaScript 闭包&基于闭包实现柯里化curry和bind

闭包:

  • 1 函数内声明了一个函数,并且将这个函数内部的函数返回到全局
  • 2 将这个返回到全局的函数内中的函数存储到全局变量中
  • 3 内部的函数调用了外部函数中的局部变量

闭包简述:

  • 有权访问另一个函数局部作用域中的变量的函数

闭包清除:

  • 将存储该内部函数的全局变量赋值为null,此时内部函数没有被引用,被垃圾回收机制回收
  • 由此也可以得出,闭包形成的原因------ 基于引用计数与标记清除的JavaScript垃圾回收机制

优点:

  • 有私有变量存在
  • 避免全局污染
  • 防止私有变量被垃圾回收

缺点:

  • 势必造成内存泄漏

示例:

        function fn1() {
            var a = 1;
            function fn2(){
                var b = 0;
                a ++;
                b++;
                console.log(a,b);
            }
            return fn2;
        }    
        var fns = fn1();
        fns();
        fns();//3,1
        //第二次执行fns,fns又创建新的执行期上下文,此间b经历了残忍地再初始化和重建
        //而a因为在fn2的局外,又为全局变量fns所庇佑,于是得以苟且偷生,并继续接下来的运算
         
        function fn1(s){
            var a = 1;
            var o = {a:1};
            return function(){
                a++;
                o.a++;
                console.log(a,o.a);
            }
        }
        var fn = fn1();
        fn();
        fn();
        fn();
        fn();//5,5
        fn = null;//清除闭包    

 

运用:

  • curring
  • bind

curring : 

1 函数多行执行

 

        /**
         闭包实现柯里化
            柯里化主要做两件事情:
                1 执行函数参数个数不为0时, 将参数列表用concat连接存储在数组arr中
                2 否则执行参数列表为arr的执行函数
            步骤:
                1 在外部函数新建一个数组arr
                2 当参数个数不为0时, arr在内部函数存储每次函数执行的参数列表, 返回并用全局变量接收内部函数, 形成闭包
                3 当前执行函数的参数个数不为0时, 将参数列表存进数组
                4 当执行函数的参数个数为0时, 执行参数列表为arr的执行函数
          
         */  
        const add = (...args) => args.reduce((a, b) => a + b)

        const curry = function (fn) {
            const args = []
            function temp(...newArgs) {
                if (newArgs.length) {
                    args.push(...newArgs)
                    return temp
                }
                return fn.apply(this, args)
            }

            temp.toString = function () {
                // console.log(add.apply(null, args));
                return add.apply(null, args);
            }

            return temp
        }


        console.log(curry(add)(1)(2, 3)());
        console.log('%s', curry(add)(2)(2, 3));

 

 bind:

/* 
           实现bind:
                   将函数中的this指向绑定到bind函数的参数中
                   用apply实现
        */
        function bind(fn, obj) {
            return function () {
                //这里的传参要看是谁调用
                console.log(arguments);//3,5,这里的参数是setTimeout传进来的
                fn.apply(obj, arguments);
            }
        }
        function abc(_a, _b) {
            this.a = _a;
            this.b = _b;
        }
        var obj = {};
        setTimeout(bind(abc, obj), 200, 3, 5);//执行function(){abc(3,5)}

 

posted @ 2020-02-19 22:32  IslandZzzz  阅读(336)  评论(0编辑  收藏  举报