八股学习-JS的闭包

一.闭包的定义

闭包是指函数和其周围的词法环境的引用的组合。

简单来说,就是函数可以记住并访问其在定义时的作用域内的变量,即使该函数在其它作用域调用。

也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。

function createCounter() {
    let count = 0;  // 私有变量
    
    return {
        increment() {
            return ++count;
        },
        getCount() {
            return count;
        }
    };
}

const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.getCount()); // 2
  • 函数携带着它定义时的作用域信息

二.闭包的原理(底层机制)

在 JS 中,每次函数执行都会创建一个执行上下文栈(Execution Context),上下文包含变量环境(Variable Environment)。当内部函数被返回或传出外部时,JavaScript 引擎会将相关变量的引用保留在内存中,不会立即销毁,从而形成闭包。

三.闭包的应用场景

①:数据封装 / 私有变量

function counter() {
    let count = 0;

    return {
        increment: () => ++count,
        decrement: () => --count,
        get: () => count
    };
}

let c = counter();
console.log(c.increment()); // 1
console.log(c.get());       // 1

②:函数工厂

function multiply(x) {
    return function(y) {
        return x * y;
    };
}

const multiplyByTwo = multiply(2);
console.log(multiplyByTwo(4)); // 8

③:事件处理



④:模块化实现

使用闭包创建私有变量和方法,形成模块化代码结构

const module = (function() {
    let privateVar = 'private';
    
    function privateMethod() {
        return privateVar;
    }
    
    return {
        publicMethod() {
            return privateMethod();
        }
    };
})();

⑤:循环中的闭包

  // 错误示例
  for (var i = 0; i < 3; i++) {
    setTimeout(() => console.log(i), 0); // 3,3,3
  }

  // 正确示例
  // 使用let和const替代var
  for (let i = 0; i < 3; i++) {
    setTimeout(() => console.log(i), 0); // 0,1,2
  }

  // 正确示例
  // 使用闭包
  for (var i = 0; i < 3; i++) {
    (function(j) {
        setTimeout(function() {
            console.log(j); // 0 1 2
        }, 100);
    })(i);
  }

四.闭包的缺点

  • 容易造成内存泄漏(引用的变量得不到释放)。

  • 调试难度增大(变量状态隐藏在函数中)。

注意内存管理

// 内存泄漏示例
function leakMemory() {
    const largeData = new Array(1000000);
    return function() {
        console.log(largeData[0]);
    }
}

// 避免内存泄漏
function avoidLeak() {
    const data = process(largeData);
    return function() {
        console.log(data);  // 只保留需要的数据
    }
}

五、闭包与垃圾回收

通常,函数执行完后其作用域就会被销毁。但闭包中被引用的变量会被保留在内存中,只要闭包仍在使用,变量就不会被回收。

这可能造成内存问题,尤其是在网页中绑定大量 DOM 事件但未解绑的情况下。

你可能感兴趣的:(前端面试准备,javascript,学习,前端,闭包,面试八股)