力扣闭包

59 阅读2分钟

哈喽哈喽,这里是小菜不拖延博主,没错,博主又新开了一个刷题的专题捏

闭包

leetcode:2620

内部函数可以访问到外部函数的作用域

可以看到本身外部是无法访问到n这个变量的,但是由于我们利于了闭包,内部函数可以访问外部作用域,外部函数返回一个内部函数,所以我们就能通过这个返回的内部函数访问到外部函数内的变量了

function f1(){
  var n = 999;
  function f2(){
    console.log(n);
  }
  return f2
}

var result = f1();
result();//999

用法

  • 读取内部函数的值
  • IIFE自执行函数 ()()相当于调用自己,所以就马上执行了
var n = 999;
(function f1(){
  console.log(n);
})()
//999

  • 封装对象的私有对象和私有方法
  • 将外部函数创建的变量值始终保存在内存当中
//代码中f1的内部变量n一直存在内存中,不会在f1调用结束后被自动清除。

function f1(){
  var n = 999;
  function f2(){
    console.log(n++);
  }
  return f2
}
var result = f1();
result();//999

垃圾回收机制

垃圾回收机制就是间歇的不定期的寻找到不再使用的变量,并释放掉它们所指向的内存

内存泄漏

就是不需要某块内存的时候这块内存还存在

垃圾回收算法

引用计数

给每一个对象分配一个引用计数器,对象被创建的初始值为1,被引用一次那么值就+1,反之-1

//hello字符对象被创建,被str1引用,所以值为1
str1 = "Hello"

//被str2引用+1 =2
str2 = str1

//str2改变指向对象,所以值-1=1
str2 = "World"

//str1要是指向别的对象,这个时候hello就会被回收

缺点:无法处理循环引用

这是因为引用计数仅仅根据对象被引用的次数进行计数,而循环引用会导致引用计数始终不为零

let a = {};
let b = {};
a.b = b;
b.a = a;
console.log(a,b)

image.png

标记清除

是一种更智能的算法,不需要额外的空间来记录对象引用的情况,在开始阶段遍历所有对象,并且打上标记,在清除阶段遍历对象,把没有被标记的对象视为垃圾进行回收

缺点:

  • 遍历和清除的过程当中会暂停程序执行
  • 可能存在误判

阅读:

如何简单理解闭包(Closure) - 掘金 (juejin.cn)