JavaScript闭包原理与执行上下文详解

作者:青柠时间:2026-10-22 01:46:09浏览:135

本文通过具体代码实例,深入解析JavaScript闭包的运行机制。重点讲解全局上下文与函数执行上下文的创建、压栈与销毁过程,阐明闭包如何维持对局部变量的引用,以及由此带来的内存开销。

JavaScript闭包原理与执行上下文详解

本文通过具体代码实例,深入解析JavaScript闭包的运行机制。


<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title></title>
  </head>
  <body>
    <script type="text/javascript">
//      第一,函数作为返回值
      function fn(){
        var max = 10;
        return function bar(x){
          if(x > max) {
            console.log(x);
          }
        };
      }
      var f1 = fn();
      f1(15);
    </script>
    <script type="text/javascript">
//      第二,函数作为参数被传递
      var max = 10;
      fn = function(x){
        if(x > max){
          console.log(x);//15
        }
      };
      (function(f){
        var max = 100;
        f(15);
      })(fn);
    </script>
    <script>
      function fn(){
        var max = 10;
        return function bar(x){
          if(if > max){
            console.log(x);
          }
        };
      }
      var f1 = fn();
        max = 100;
      f1(15);
    </script>
  </body>
</html>

首先,在代码执行前会生成全局上下文环境,并在执行过程中对其中定义的变量进行赋值,此时全局上下文处于活动状态。

在全局上下文中,变量max的初始值为undefined。

接着,执行var f1 = fn();语句时,调用fn()函数,系统会创建fn()的执行上下文环境并将其压入栈中,同时设为活动状态。

在fn()的执行上下文中,局部变量max被赋值为10。

当var f1 = fn();执行完毕后,fn()函数的调用理应结束。按照常规逻辑,其执行上下文环境应当被销毁。

然而,关键点在于:fn()函数返回的是一个内部函数。函数的特性之一是能够创建独立的作用域。

巧合的是,返回的这个内部函数体中引用了一个自由变量max,该变量指向fn()作用域下的执行上下文中的max值。

因此,这个max变量不能被销毁,否则内部函数在访问max时将无法找到对应的值。这意味着fn()的执行上下文环境必须保留,并继续存在于执行上下文栈中。

当代码执行到max = 100;时,全局上下文环境重新变为活动状态,但fn()的执行上下文环境依然驻留在执行上下文栈中。

执行完max = 100;后,全局上下文中的max变量被重新赋值为100。

此时,全局上下文环境中的max值为100,而fn()执行上下文环境中的max值仍保持为10。

随后,执行f1(15);语句,即调用内部函数bar(15)。系统会创建bar(15)的执行上下文环境,并将其设为活动状态。

在bar(15)执行期间,max作为自由变量,需要向创建bar函数的作用域链中查找,最终在fn()的作用域中找到了max,其值为10。

这里的核心逻辑在于:bar函数是在执行fn()时创建的。尽管fn()早已执行结束,但其执行上下文环境仍保留在栈中,因此bar(15)能够成功查找到max。如果fn()的执行上下文被销毁,max变量将无法被访问。

由此可见,使用闭包会增加内存内容的开销,这一点在上述过程中已十分明显。

最后,执行完f1(15);后,进入上下文环境的销毁过程,此处不再赘述。

闭包与作用域、执行上下文环境之间有着密不可分的关系,理解起来确实具有一定挑战性。

此外,闭包在jQuery等库中的应用非常广泛。无论是研究经典框架、类库,还是自行开发插件,掌握闭包、原型等基础理论都是必要的。否则,遇到BUG时可能因超出知识范围而难以排查。

更多关于JavaScript相关内容可查看本站专题:《javascript面向对象入门教程》、《JavaScript中json操作技巧总结》、《JavaScript切换特效与技巧总结》、《JavaScript查找算法技巧总结》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》

希望本文所述对大家JavaScript程序设计有所帮助。

作者最新文章