JavaScript基础知识讲解——闭包的原理与作用

113 阅读3分钟

在对JavaScript这门语言的学习过程中,我们一定会听到闭包这个词,这篇文章就是为大家讲解闭包它的原理和作用。当然,在了解闭包之前我们还需要了解调用栈和作用域链这两个重要的概念。


  1. 什么是调用栈
  2. 什么是作用域链
  3. 闭包的原理和作用

什么是调用栈

在代码执行之前编译器会对代码进行预编译,此时会产生一个调用栈,调用栈里存放了程序在执行过程中函数调用的顺序和位置。函数在调用栈里的执行遵循先进后出,后进先出的规则。当函数执行完毕后,对应的栈帧会被从调用栈中移除,程序会回到上一个函数的执行点继续执行。当发生函数嵌套调用或递归调用时,调用栈可以追踪多层次的函数调用关系,确保每个函数能够正确返回并继续执行。

总之,调用栈是用于管理函数调用关系的数据结构,记录了程序在执行过程中函数调用的顺序和位置,同时也负责管理函数的执行上下文。

image.png

什么是作用域链

通过词法环境来确定某作用域的外层作用域,查找变量由内而外的这种链状关系,叫作用域。在JavaScript中,每个函数都有自己的作用域。当在函数内部访问一个变量时,JavaScript 引擎会先在当前函数的作用域中查找该变量,如果找不到,就会沿着作用域链向上一级作用域查找,直到找到该变量或者到达全局作用域为止。

作用域链的形成是由函数创建的时候确定的,它基本上是静态的,在函数定义的时候就已经确定了。这也意味着内部函数可以访问外部函数的变量,因为内部函数的作用域链包含了外部函数的作用域。

案例

    console.log(myName);
}
function foo(){
    var myName ='tg'
    bar()
}

var myName='wz'
foo()

箭头指向代表作用域链即查找顺序

image.png

闭包的原理和作用

在js中根据词法作用域的规则,内部函数总是能访问外部函数中的变量的,当通过调用一个外部函数返回一个内部函数后,即使外部函数已经执行完毕,但是内部函数引用了外部函数中的变量依然会保存在内存中,我们把这些变 量的集合叫做闭包。

-优点:

  1. 可以实现私有化变量和数据的封装,防止外部访问和修改。
  2. 可以创建具有持久状态的函数,即使外部函数执行结束,闭包中的变量仍然可以被访问和操作。
  3. 可以模拟面向对象编程的一些特性,如对象的私有属性和方法。

-缺点:内存泄漏

案例

    function b(){
        var num =1
        console.log(count);
    }
    var count =2
    return b
}
var c=a()

image.png

总结

调用栈是一种用来管理函数调用关系的数据结构,而作用域链则通过词法环境确定某个作用域的外层作用域,实现变量的查找由内而外的链状关系。闭包是JavaScript中的一个重要概念,它允许内部函数访问外部函数中的变量,并且这些变量在外部函数执行完毕后仍然保存在内存中,从而实现了私有化变量的效果。