js进阶之闭包

47 阅读2分钟

闭包生成条件

  1. 函数嵌套
  2. 内部函数引用外部函数变量(函数)

function a() { 
  var constant = 111;
  function f() { 
    var b = 222;
    console.log(b,constant)
  }

  f()
}
// 在外部函数执行时就产生了闭包
a();

闭包什么时候产生?

外部函数执行时就产生了。

为什么?不应该是内部函数执行时才产生吗?

以上代码中,在执行a函数的第一行时,也就是constant变量未赋值之前,就会在内部函数f上创建一个closure对象

这个对象就是闭包对象,此时对象值为{constant:undefined} 当执行内部函数时,此对象为{constant:111}

总结:闭包是存在于内部函数的一个对象。

闭包作用

  1. 在函数执行结束后,仍然可以使用其内部变量(函数),延长局部变量的生命周期
  2. 外部可以在不访问对象内部变量的情况下,调用其内部方法,即开发者可以只暴露安全的方法给用户,而不让用户访问到自己的私有变量。
function a() { 
  var constant = 1;
  return function f() { 
    constant++;
    console.log(constant)
  }
}
let b = a();

b(); // 2

b(); // 3

观察以上代码,在函数a执行结束后,a内的所有变量和函数应该都被垃圾回收机制回收,但是闭包导致constant这个变量,还一直为我们所用。

(function() { 
  let name = 'jack'
  let age = 11;

  function alertName(){ 
    alert(name)
  }

  function addAge() { 
    age++;
    console.log(age);
  }

  window.addAge = addAge;
  window.alertName = alertName;
})()

window.addAge()

window.addAge()

以上代码就是js最初的模块化代码,通过立即执行函数(IIFE)来包裹变量,实现变量隔离的作用。

同时,又可以通过闭包向外暴露方法,从而实现间接操作内部变量的功能。

闭包回收

闭包在什么时候会消失呢?

内部函数被回收的时候。

function a() { 
  var constant = 1;
  return function f() { 
    constant++;
    console.log(constant)
  }
}
let b = a();

b(); // 2

b(); // 3
// 手动回收闭包
b = null

闭包应用

  1. 任何函数嵌套、内部函数调用外部函数变量的行为
  2. 创建js模块
  3. react中useEffect、useMemo等都在使用闭包