无处不在的闭包

234 阅读2分钟

「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战

人要生存,就要不断地从大自然中索取养料,喝大自然的水,吃大自然里的食物。同理,闭包想要存在,就要能够获取到其所处的词法作用域中的变量或方法。

JavaScript 天然地就为闭包的出世提供很好的环境,可以说只要有一个函数的诞生,就会伴随着一个闭包的形成。

在闭包被创建之时,函数就直接去获取了它所在词法作用域内的所有的局部变量。因此,闭包可以把函数及其所操作的变量连接到一起。

闭包的优势:(数据的隔离和封装)

  • 模拟私有方法,外部函数只能通过预留出来的 API 接口,来实现相应的功能,同时也提升了代码的安全性

闭包的不足:(循环陷阱)

  • 循环的每层函数之间共享同一个词法作用域,因此指向相同,最后得到的结果也都是一致的。—— —— 这个问题也可以通过即时函数、let、foreach 来解决
  • 内存的消耗,因此也会带来一些性能上的负面作用。

闭包展示:

function fun() {
    var str = "string";
    function backstr() {
        alert(str);
    }
    return backstr;
}

var myFun = fun();
myFun();
function add(a) {
  return function(b) {
    return a + b;
  };
}

var add8 = add(8);
var add9 = add(9);

console.log(add8(4));  // 12
console.log(add9(4));  // 13
var Count= (function() {
  var num = 0;
  function change(val) {
    num += val;
  }
  return {
    add: function() {
      change(1);
    },
    dec: function() {
      change(-1);
    },
    val: function() {
      return num;
    }
  }
})();

console.log(Count.val()); /* logs 0 */
Count.add();
Count.add();
Count.add();
console.log(Count.val()); /* logs 3 */
Count.dec();
console.log(Count.val()); /* logs 2 */
Count.dec();
console.log(Count.val()); /* logs 1 */

由于闭包会占用比普通函数的更多的内存空间,来保护其所需要的变量不被浏览器的垃圾回收机制回收 ♻️,如果过度地使用闭包,也会导致内存的泄漏,因此要慎用闭包。

鉴于闭包经常会存在于js中,我们也可以通过即时函数,让闭包只执行一次;或者通过let 来定义变量,从而让循环的每次的变量之间不会互相干扰。

闭包好处多多,缺点多多,作为前端开发的小伙伴们,一定要对它提升警觉呦,努力让它称为程序的帮手。