浅谈JS闭包

471 阅读3分钟

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

JS闭包可以说是一个很高频的面试题,而且非常的抽象,不容易理解,作为前端小白的我也时常搞不清楚,在查阅部分资料后谈谈个人对JS闭包的一个浅显的理解。

先讲讲作用域作用域又分为全局作用域和局部作用域

  • 全局作用域
  • 局部作用域 1.全局作用域定义的函数或者变量不会被销毁,全局作用域定义的变量在其他地方也能被使用

2.当变量在局部作用域声明,那这个变量就是这个作用域的局部变量,局部变量在使用后将会被垃圾回收机制回收。

<script>
let b = 1                   //b在script标签下定义即为全局变量
function show(){
  let a = 5
  console.log(a)//5         //在函数show中定义,为show函数的局部变量
  console.log(b)//1         //局部没有定义b,那么此时就会向上一层查找
}                           //如果第二层查找找不到,就会一直往上,直到找到全局变量
show()
console.log(a)//Uncaught ReferenceError: a is not defined   
//由于a定义在函数show中,而全局中也找不到a,那么就会报错。
console.log(b)//1
</script>

换个简单的图助于理解,在全局作用域中访问变量a,明显是得不到,因为a是show的私有变量。而在函数show开辟的作用域中首先找不到b就会向他的父级查找,找到变量b。

image.png

个人浅显理解,作用域==作用范围。即在该作用范围内,我都能辐射,影响到你,能够被使用到,举个栗子。理解了作用域的概念那么接下来看看JS的闭包。

切入正题JS闭包

  • 概念:指的是那些引用了另一个函数作用域中变量的函数,通常是在嵌套函数中实现的。通俗一点,用个人的理解就是一个函数中返回了另一个函数,那么就形成了闭包。

  • 优缺点:

      优点:
         1.延长变量声明周期     
         2.避免全局变量的污染,保证私有变量
    

在这里提一句,vue中常问为什么data是一个return返回的函数。其实这里也用到了闭包,保证了私有变量,使得各个组件之间的数据都是单独的,不会互相污染。

    缺点:
       1.常驻内存 会增大内存的使用量 使用不当会造成内存泄露
       2.由于闭包涉及跨域访问,所以会导致性能损失

利用图解和代码来看一看闭包。

function show(){
  let a = 1
  function show2(){
    console.log(++a)
  }
  show2()
}
show()//2
show()//2

显然如果你想让a变量持续增加是不太行的,因为每次执行一遍show函数都会开辟一块新的内存空间来存储show函数,也就是开辟一块新的函数作用域。那么就可以通过闭包来实现累加。

function show(){
  let a = 1
  return function show2(){
    console.log(++a)
  }
}
let hd = show()
hd()//2
hd()//3
let hq = show()
hq()//2

show方法返回一个函数用变量hd接收,接着hd()执行返回的这个函数show2,而show2用到了show函数中的变量a,因为show2还在使用着,垃圾回收机制也就会受不了,同样的show,a和show2是一起的都不会被回收就会一直存在。那么a的值也就会改变。至于为什么hd和hq会不同,因为再用变量接收的时候,也是开辟的两块空间进行接收。这个也和vue中的data很类似,不同的data函数之间不会相互污染。

image.png

感谢读者大大的阅读,作为一个前端小白,写作的内容多少会有点瑕疵,如果写的文章有不好值得纠正的地方,欢迎各位读者大大们的指正和探讨。