原生JS知识点复习之关于闭包的理解

149 阅读2分钟

闭包

  • 闭包的定义:
    • 函数执行就会形成一个私有作用域从而保护变量不会被外界变量干扰这种保护机制称为闭包
    • 但是严格来说闭包应该是一个不被销毁的私有作用域该栈内存一直存在于window中

闭包应用:

  1. 柯里化函数

    柯里化函数的思想就是把多阐述的函数变成单参数的函数

function add(a,b,c){
    return a+b+c;
}
console.log(add(1,2,3)); 6
function add2(a){
    return function (b){
        return function (c){
            return a + b + c;
        }
    }
}
console.log(add2(1)(2)(3)); // 6
 这么做 有什么意义?

  1. 柯里化函数的意义?
    1. 尽可能的函数化
    2. 减少代码冗余,增加代码可读性
        const curry = (fn, args = []) => {
            let num = fn.length; // 形参个数
            // args 形参存在的意义?

            return (...a) => {
                console.log("a", a);
                let arg = args.concat(a); // 将每次回调函数的形参保存下来
                // 疑问:
                // 为什么 不在return的返回函数中用一个变量保存每次进来的形参呢
                // 这是因为返回函数也就是add每次执行完毕作用域销毁了
                // 这时保存在此作用域的变量也就没有了,将会一起被浏览器回收
                // 所以我们需要利用闭包的机制记录保存每次进来的形参 
                // 所以还记得闭包的机制吗?
                // - 闭包的定义:
                //     - 函数执行就会形成一个私有作用域从而保护变量不会被外界变量干扰这种保护机制称为闭包
                //     - 但是严格来说闭包应该是一个不被销毁的私有作用域该栈内存一直存在于window中
                // add 函数一共执行了五次每次都会在上级作用域(curry函数中)开辟一个栈内存但是每次都会执行完毕被浏览器销毁
                // 但curry函数因为有了add 的多次执行导致该栈内存没有被浏览器销毁(curry: 老子还有用呢别急着就给我干掉了!!!; 浏览器: 哦知道了就你事多)
                // 这时arge也就有了用武之地
                // console.log("args1", args);
                // console.log("arg", arg)
                if (arg.length < num) { // 当add的执行彻底完毕将不进入此判断
                    // console.log("args2", args);
                    // console.log("arg.length", arg.length);
                    return curry(fn, arg);
                }
                return fn(...arg); // 最终彻底结束,并销毁curry这个fn的父级作用域
            }
        }

        function add1(a, b, c, d, e) {
            return a + b + c + d + e
        }
        let add = curry(add1)
        // console.log(add)
        console.log(add(1)(2)(3,4)(5))