Closure Currying

What is a closure

  • Closure refers to a function that has access to variables in the scope of another function.
    The most common way to create a closure is to create another function within a function and access the local variables of this function through another function.

    function fn1(){
                var a=1;
                // 因为返回的函数被存储在全局变量中,
                // 并且这个返回的函数使用这个a的局部变量,因此a被保存在堆中
                //闭包会产生内存泄漏
                return function(){
                    a++;
                    console.log(a);
                }
            }
    
    
            var f=fn1();
            f()
            f(); 
    

Features and advantages of closures

Characteristics of closures

  1. Function nested function
  2. The function can reference external parameters and variables
  3. Parameters and variables will not be recycled by the garbage collection mechanism

Advantages of closures

  1. Avoid pollution of global variables
  2. In order to get private variables
  3. Hope that a variable resides in memory for a long time

Disadvantages of closures

  1. Will cause a memory leak
var Utils=(function(){
         var num=0;
            return {
                a:function(){
                    num++;
                    console.log(num);
                },
                b:function(){

                }
            }
        })();
        

        Utils.a();
        Utils.a();
        Utils.a();

Currying

What is currying

  • It refers to the method of converting a multi-parameter function into a single-parameter function

  • Collect parameters for storage, and execute the actual function to be processed when there are no parameters

function curry(fn){
        var arr=[];
        return function(){
            if(arguments.length>0){//有参数传入
                arr=arr.concat(Array.from(arguments));//将arguement转化为数组放进去
                return arguments.callee;//自身函数
            }else{//没有传参
               return  fn.apply(null,arr);
            }
           
        }
    }

    function fns(){//解决实际融合问题
        return Array.from(arguments).reduce((value,item)=>value+=item);//求和
    }


  var s=fns(1,2,3,4,5,6)
    console.log(s);
    var sum=curry(fns);
   var s=sum(1)(2,3)(4,5,6)()
   console.log(s);

Currying advantages

  • 1. Parameter reuse
// 正常正则验证字符串 reg.test(txt)

// 函数封装后
function check(reg, txt) {
    return reg.test(txt)
}

check(/\d+/g, 'test')       //false
check(/[a-z]+/g, 'test')    //true

// Currying后
function curryingCheck(reg) {
    return function(txt) {
        return reg.test(txt)
    }
}

var hasNumber = curryingCheck(/\d+/g)
var hasLetter = curryingCheck(/[a-z]+/g)

hasNumber('test1')      // true
hasNumber('testtest')   // false
hasLetter('21212')      // false
  • 2. Confirm in advance
  • 3. Delayed operation
Function.prototype.bind = function (context) {
    var _this = this
    var args = Array.prototype.slice.call(arguments, 1)
 
    return function() {
        return _this.apply(context, args)
    }
}//bind是柯里化

Packaging method

// 初步封装
var currying = function(fn) {
    // args 获取第一个方法内的全部参数
    var args = Array.prototype.slice.call(arguments, 1)
    return function() {
        // 将后面方法里的全部参数和args进行合并
        var newArgs = args.concat(Array.prototype.slice.call(arguments))
        // 把合并后的参数通过apply作为fn的参数并执行
        return fn.apply(this, newArgs)
    }
}

// 支持多参数传递
function progressCurrying(fn, args) {

    var _this = this
    var len = fn.length;
    var args = args || [];

    return function() {
        var _args = Array.prototype.slice.call(arguments);
        Array.prototype.push.apply(args, _args);

        // 如果参数个数小于最初的fn.length,则递归调用,继续收集参数
        if (_args.length < len) {
            return progressCurrying.call(_this, fn, _args);
        }

        // 参数收集完毕,则执行fn
        return fn.apply(this, _args);
    }
}

Currying performance

  • Accessing the arguments object is usually slower than accessing named parameters
  • Some older browsers are quite slow in implementing arguments.length
  • Using fn.apply(…) and fn.call(…) is usually slightly slower than calling fn(…) directly
  • Creating a large number of nested scopes and closure functions will bring costs, both in memory and speed
  • In fact, in most applications, the main performance bottleneck is operating on DOM nodes. The performance loss of this js is basically negligible, so curry can be used directly and safely.

Anti-Currying

  • The meaning and usage are just the opposite compared to function currying, which expands the scope of application and creates a function with a wider application range. Extend methods that were originally applicable only to specific objects to more objects

Guess you like

Origin blog.csdn.net/w_cyj/article/details/107991733