js中闭包
Published on Jan 30, 2023, with 16 view(s) and 0 comment(s)
Ai 摘要:闭包是JavaScript中函数与其词法环境的组合,允许内部函数访问外部函数的变量。示例中,`bar`函数通过闭包保留了`foo`函数的`name`变量,即使`foo`执行完毕。闭包由函数和自由变量组成,可能导致内存泄漏(需手动释放),但也能实现变量持久化、封装私有属性和方法。例如,计数器函数通过闭包保持独立状态,实现各自变量的递增。

示例:

function foo() {
  var name = "foo";
  var age = 18;
  function bar() {
    console.log("bar", name);
  }
  return bar;
}
var fn = foo();
fn();
// bar foo

案例中定义了一个函数foo,并且将foo返回值bar赋值给了fn,执行fn函数。发现仍然可以打印出来name,按理说在 *var fn = foo(); 时,foo函数的调用栈就已经被销毁,怎么在执行fn函数时还能够访问的到呢?这就形成了闭包。

内存分析:

Description

当执行完foo函数,GO对象中的fn指向foo函数中的bar函数对象,因为bar函数对象的父级作用域指向foo函数的AO对象,所以foo函数中的变量name并不会被销毁。这样当fn函数执行了一次,foo的AO对象和bar函数对象不会被销毁,就会产生内存泄漏。可以手动指定 fn = null 来销毁。

定义:

  • 闭包在实现上是一个结构体,它存储了一个函数和一个关联的环境。闭包跟函数最大的区别在于,当捕捉闭包的时候,它的自由变量会在捕捉时确定,这样即使脱离了捕捉时的上下文,它也能照常运行。

  • 闭包是两部分组成:函数+可以访问的自由变量

用途:

  • 1,从外部读取函数内部的变量。上述示例中可以访问打印name

  • 2,将创建的变量的值始终保持在内存中,上述示例会导致内存泄漏,使name始终存在于内存中

  • 3,封装对象的私有属性和私有方法

function f1(n) {
  return function () {
    return n++;
  };
}
var a1 = f1(1);
a1() // 1
a1() // 2
a1() // 3
var a2 = f1(5);
a2() // 5
a2() // 6
a2() // 7
//这段代码中,a1 和 a2 是相互独立的,各自返回自己的私有变量。